为什么在Firefox上,这些Javascript for循环比在Chrome/Safari上慢得多? [英] Why are these Javascript for loops significantly slower on Firefox then Chrome / Safari?

查看:49
本文介绍了为什么在Firefox上,这些Javascript for循环比在Chrome/Safari上慢得多?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在搞弄基准站点,我得出的结论是性能上的差异不是完全归因于循环迭代,如此版本的测试用例所示.如您所见,Firefox速度较慢,但​​差距没有我们在初始测试用例中看到的那么大.

那为什么要声明

  data [index] = data [index] * 2; 

在Firefox上慢得多?

解决方案

数组在JavaScript中比较棘手.创建它们的方式,填充它们的方式(以及用什么值填充)都会影响它们的性能.

引擎使用两种基本实现.最简单,最明显的一个是连续的内存块(就像一个C数组,带有一些元数据,如长度).这是最快的方法,理想情况下是大多数情况下所需的实现.

问题是,仅通过分配给任意索引而留下空洞",JavaScript中的数组就会变得非常大.例如,如果您有一个小阵列:

  var数组= [1,2,3]; 

,然后为大索引分配一个值:

  array [1000000] = 4; 

您将得到一个像这样的数组:

  [1、2、3,未定义,未定义,未定义,...,未定义,4] 

为节省内存,大多数运行时会将 array 转换为稀疏"数组.基本上,哈希表就像常规的JS对象一样.一旦发生这种情况,对索引的读取或写入将从简单的指针算术变为复杂得多的算法,并且可能具有动态内存分配.

当然,不同的运行时会使用不同的启发式方法来决定何时将一种实现转换为另一种实现,因此,在某些情况下,例如针对Chrome进行优化可能会损害Firefox的性能.

在您的情况下,我最好的猜测是向后填充数组会导致Firefox使用稀疏数组,从而使其运行速度变慢.

I was messing around with the benchmark site jfprefs and created my own benchmark at http://jsperf.com/prefix-or-postfix-increment/9.

The benchmarks are variations of Javascript for loops, using prefix and postfix incrementors and the Crockford jslint style of not using an in place incrementor.

for (var index = 0, len = data.length; index < len; ++index) {
  data[index] = data[index] * 2;
}

for (var index = 0, len = data.length; index < len; index++) {
  data[index] = data[index] * 2;
}

for (var index = 0, len = data.length; index < len; index += 1) {
  data[index] = data[index] * 2;
}

After getting the numbers from a couple of runs of the benchmark, I noticed that Firefox is doing about 15 operations per second on average and Chrome is doing around 300.

I thought JaegerMonkey and v8 were fairly comparable in terms of speed? Are my benchmarks flawed somehow, is Firefox doing some kind of throttling here or is the gap really that large between the performance of the Javascript interpreters?

UPDATE: Thanks to jfriend00, I've concluded the difference in performance is not entirely due to the loop iteration, as seen in this version of the test case. As you can see Firefox is slower, but not as much of a gap as we see in the initial test case.

So why is the statement,

data[index] = data[index] * 2;

So much slower on Firefox?

解决方案

Arrays are tricky in JavaScript. The way you create them, how you fill them (and with what values) can all affect their performance.

There are two basic implementations that engines use. The simplest, most obvious one is a contiguous block of memory (just like a C array, with some metadata, like the length). It's the fastest way, and ideally the implementation you want in most cases.

The problem is, arrays in JavaScript can grow very large just by assigning to an arbitrary index, leaving "holes". For example, if you have a small array:

var array = [1,2,3];

and you assign a value to a large index:

array[1000000] = 4;

you'll end up with an array like this:

[1, 2, 3, undefined, undefined, undefined, ..., undefined, 4]

To save memory, most runtimes will convert array into a "sparse" array. Basically, a hash table, just like regular JS objects. Once that happens, reading or writing to an index goes from simple pointer arithmetic to a much more complicated algorithm, possibly with dynamic memory allocation.

Of course, different runtimes use different heuristics to decide when to convert from one implementation to another, so in some cases, optimizing for Chrome, for example, can hurt performance in Firefox.

In your case, my best guess is that filling the array backwards is causing Firefox to use a sparse array, making it slower.

这篇关于为什么在Firefox上,这些Javascript for循环比在Chrome/Safari上慢得多?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆