有什么方法可以提高JavaScript数组的性能?

7
我正在将我的一些OpenGL代码迁移到WebGL,JavaScript没有真正的数组这一事实让我感到难过。我可以使用Float32Array(以及其他ArrayBuffer类型),但这似乎并没有帮助提高性能。
为了比较Array与Float32Array与Float64Array的性能,我进行了一个实验,在100000个浮点数上计时气泡排序,看看是否有任何差别:
function bubbleSort(array) {
    var N = array.length;
    for (var i = 0; i < N; i++) 
        for (var j = i; j < N-1; j++)
            if (array[j] > array[j+1]) {
                var tmp = array[j];
                array[j] = array[j+1];
                array[j+1] = tmp;
            }
}

// var nums = new Array(100000);        // regular 'JS' array
// var nums = new Float32Array(100000);   // actual buffer of 32-bit floats
var nums = new Float64Array(100000);   // actual buffer of 64-bit floats
for (var i = 0; i < nums.length; i++)
    nums[i] = Math.random() * 1000;

bubbleSort(nums);

for (var i = 0; i < nums.length; i++)
    console.log(nums[i]);

差别不大。实际上,编译器需要一些静态类型信息来优化bubbleSort函数中的array参数,以获得更好的性能。我们在JS中只能忍受糟糕的数组性能吗?有没有其他方法可以解决这个问题?除了使用ASM.js之外...


4
你是如何测试的?你确定不是因为调用了 10 万次 Math.random() 导致性能问题吗? - Rob
1
@Rob 移除 bubbleSort 并立即完成。 - wcochran
4
“冒泡排序”和“性能”这样的词汇在一篇文章中似乎是个矛盾修辞。 - user949300
2
我很惊讶那些没有抓住重点的人。它本来就应该很慢!我只是想比较JS数组和类型化数组。我本可以只做一亿个随机交换,但我希望大部分时间都花在数组索引上... - wcochran
如果你想要性能,为什么不使用无符号8位缓冲区?浮点数对性能影响很大,而且,在JS中的每个数字都是浮点数...这就引出了下一个问题;为什么要采用手动排序,当你可以调用内置方法时,它将会分配到本地代码,这肯定比你编写的任何东西更快?我认为这是两种非常快速和简单的提高JS数组性能的方法;也就是说,让浏览器的内部处理优化。在手机浏览器上以60fps运行Q3A相当令人印象深刻。 - Norguard
显示剩余4条评论
1个回答

6
您应该看到这个答案:What is the performance of Objects/Arrays in JavaScript? (specifically for Google V8),以下是其中的一些要点:
  • 使用 Array.push( data ); 比 Array[nextIndex] = data 快近20倍。
  • V8数组写入略快于读取。
所以,看起来在JS中,Array的索引速度较慢。如果性能测试中确实写入比读取更快,则动态分配可能不挑剔放置数据的位置(最快的位置?),但是在读取时,将需要跳转到许多内存地址,因此速度会慢得多。
我很想知道如果您使用文字语法[0, 1, 2,…,100000]来声明数组,性能是否会更好?
(如果有时间,我可以设置一个JSPerf)。

1
太好了 - 谢谢!我想一些(早期)实现只是对索引进行哈希处理,就像处理字符串一样 - 然后当然删除应该很快。我正在使用使用V8的Node进行测试。需要更多测试... - wcochran

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接