JavaScript数组迭代方向

当处理一个非常大的统一(同types)JavaScript对象的内存数组(每个只有几列)时…

是否对性能和/或任何其他惩罚有任何影响,当select迭代通过它作为行 – >列与列 – >行?

我们有一个来自CSV文件的100,000个数据行,每个数据行都是一个有10个整数值的对象,我们需要触摸它的每个值进行一定的计算。

无论是垂直还是水平迭代,它会有什么区别吗? 现代V8是否在乎这样的事情?

var data = [...]; // array of many same-type objects; // horizontal iteration: for (var p in data[0]) { for (var i = 0; i < data.length; i++) { var value = data[i][p]; // current value; // calculate here from the value; } } // vertical iteration: for (var i = 0; i < data.length; i++) { for (var p in data[0]) { var value = data[i][p]; // current value; // calculate here from the value; } } 

只有一个方法可以肯定的是运行一些基准testing,我做了一个jsperf: http ://jsperf.com/vertical-vs-horizo​​ntal-loop结果取决于预期的引擎。 早期的testing结果(Chrome 42是Window 10上的Edge):

 | UserAgent | horizontal iteration | vertical iteration | vertical iteration with caching | # Tests | |:----------------:|:--------------------:|:------------------:|:-------------------------------:|:-------:| | Chrome 42.0.2311 | 1,067 | 287 | 226 | 2 | | Firefox 43.0 | 5,621 | 415 | 443 | 2 | | IE 11.0 | 976 | 441 | 313 | 2 | | Iron 46.0.2450 | 1,557 | 901 | 1,907 | 2 | (numbers are ops/s, the higher the better) 

有趣的是,水平迭代的速度是Firefox的两倍到十几倍。 但是,使用caching的垂直迭代是最快的,只有在铁46(Chromium fork所以V8引擎)上。

基准节点v5.1.0:

水平迭代x 1,140 ops / sec±1.11%(63次采样)
垂直迭代x 833 ops / sec±0.92%(68次采样)
垂直迭代cachingx 1678 ops / sec±1.13%(67次采样)
最快的是与caching垂直迭代

反向垂直更好地提高内存利用率和性能。 我会说反向数据数组。 考虑到一些小的事情是用i += 1递增而不是i++++i 。 但是,当你迭代大数组时,这将显示非常小的性能优势。 如果你问我,我遵循以下任一种方法

  1. 使用asynchronous库的each函数遍历数据数组并执行操作。 它们的优点是真正的asynchronous,所以不会阻塞执行线程。 我已经使用这个库来比较两个大型数组,其中每个数组操作包括绘制HTML到canvas和比较。 asynchronousjs为我做了这个工作非常好。
  2. 根据用户机器创buildworker(n)个线程,然后将大数组切片为更小的数据块,为分块数组的工作人员提供数据。 无论哪个工作者首先完成将从队列中select另一个分块数组。 最后你可以汇总结果。 我自己testing了这个方法。 我试图sorting一个50K数组项目的数组。 经常执行浏览器被阻止,但用这种方法,它能够完成完美的罚款。 我甚至尝试过300K项目。 我会说,如果你不支持低端浏览器,这是更好的方法。

垂直显然好多了,因为你可以cachingdata[i]并且在检查属性之前只查看一次。

 // vertical iteration: for (var i = 0; i < data.length; i++) { var obj = data[i] // <--- here for (var p in obj) { var value = obj[p]; // current value; // calculate here from the value; } }