JavaScript数组迭代方向

时间:2016-02-13 03:14:23

标签: javascript node.js

处理一个非常大的内存数组的统一(相同类型)JavaScript对象(每个只有几列)...

在选择将其作为row->列与列 - >行进行迭代时,是否会对性能和/或任何其他惩罚产生影响?

示例

我们从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;
    }
}

3 个答案:

答案 0 :(得分:2)

只有一种方法可以确定是运行一些基准测试,我制作了一个jsperf:http://jsperf.com/vertical-vs-horizontal-loop结果取决于引擎的预期效果。我做过测试的早期结果(Chrome 42是Edge on Window 10):

|     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上)。但是,使用缓存的垂直迭代是Iron 46(Chromium fork所以V8引擎)上最快的。

节点v5.1.0的基准:

  

水平迭代x 1,140 ops / sec±1.11%(63次运行采样)
  垂直迭代x 833 ops / sec±0.92%(68次运行采样)
  垂直迭代,缓存x 1,678 ops / sec±1.13%(67次运行采样)
  最快的是使用缓存的垂直迭代

答案 1 :(得分:0)

反向垂直更好地提高了内存利用率和性能。我会说反向迭代数据数组。要考虑的一些小问题是使用i += 1代替i++++i来增加i。但是,当您在大型阵列中进行迭代时,这些将显示非常小的性能优势。如果你问我,我会遵循以下任何一种方法

  1. 使用异步库的each函数迭代数据数组并执行操作。优点是它们是真正异步的,因此不会阻塞执行线程。我已经使用这个库来比较两个大型数组,其中每个数组操作包括绘制html到画布和比较。 Async js对我来说做得很好。
  2. 根据用户计算机创建worker(n)个线程,然后将大型数组切成较小的块,使用分块数组提供工作者。无论哪个工作者首先完成,都会从队列中选择另一个分块数组。最后,您可以汇总结果。我自己测试了这种方法。我试图对50K数组项进行排序。通过常规执行浏览器被阻止,但通过这种方法,它能够完美地完成。我甚至试过300K物品。我想说,如果你不支持低端浏览器,这是更好的方法。

答案 2 :(得分:0)

垂直显然要好得多,因为你可以缓存data[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;
    }
}