为什么在 V8 中使用此代码片段 <= 比 < 慢?

2024-01-23

我正在阅读幻灯片使用 V8 突破 Javascript 速度限制 https://v8-io12.appspot.com/#16,并且有一个类似下面代码的示例。我不明白为什么<=慢于<在这种情况下,有人能解释一下吗?如有任何意见,我们将不胜感激。

Slow:

this.isPrimeDivisible = function(candidate) {
    for (var i = 1; i <= this.prime_count; ++i) {
        if (candidate % this.primes[i] == 0) return true;
    }
    return false;
} 

(提示:primes 是一个长度为 prime_count 的数组)

Faster:

this.isPrimeDivisible = function(candidate) {
    for (var i = 1; i < this.prime_count; ++i) {
        if (candidate % this.primes[i] == 0) return true;
    }
    return false;
} 

[更多信息]速度提升显着,在我本地环境测试,结果如下:

V8 version 7.3.0 (candidate) 

Slow:

 time d8 prime.js
 287107
 12.71 user 
 0.05 system 
 0:12.84 elapsed 

Faster:

time d8 prime.js
287107
1.82 user 
0.01 system 
0:01.84 elapsed

其他答案和评论提到两个循环之间的区别在于第一个循环比第二个循环多执行一次迭代。这是事实,但在一个增长到 25,000 个元素的数组中,多一次或少一次迭代只会产生微小的差异。作为一个大概的猜测,如果我们假设其增长的平均长度为 12,500,那么我们预期的差异应该约为 1/12,500,或仅为 0.008%。

这里的性能差异比一次额外迭代所解释的要大得多,并且该问题在演示文稿接近尾声时得到了解释。

this.primes是一个连续的数组(每个元素都有一个值)并且元素都是数字。

JavaScript 引擎可以将这样的数组优化为实际数字的简单数组,而不是恰好包含数字但可能包含其他值或不包含值的对象数组。第一种格式的访问速度要快得多:它需要更少的代码,并且数组要小得多,因此它更适合缓存。但有些条件可能会阻止使用这种优化格式。

一种情况是某些数组元素丢失。例如:

let array = [];
a[0] = 10;
a[2] = 20;

现在的价值是多少a[1]? It 没有价值。 (说它具有价值甚至是不正确的undefined- 包含以下内容的数组元素undefined值与完全缺失的数组元素不同。)

没有办法仅用数字来表示这一点,因此 JavaScript 引擎被迫使用优化程度较低的格式。如果a[1]与其他两个元素一样包含一个数值,该数组可能会被优化为仅包含数字的数组。

数组被强制采用去优化格式的另一个原因可能是您尝试访问数组边界之外的元素,如演示中所述。

第一个循环与<=尝试读取超出数组末尾的元素。该算法仍然可以正常工作,因为在最后一次额外迭代中:

  • this.primes[i]评估为undefined因为i超出了数组末尾。
  • candidate % undefined(对于任何值candidate) 评估为NaN.
  • NaN == 0评估为false.
  • 因此,return true没有被执行。

所以就好像额外的迭代从未发生过——它对其余逻辑没有影响。该代码产生的结果与没有额外迭代的结果相同。

但为了到达那里,它尝试读取超出数组末尾的不存在的元素。这迫使阵列退出优化——或者至少在本次演讲时是这样。

第二个循环与<仅读取数组中存在的元素,因此它允许优化数组和代码。

问题描述于第 90-91 页 https://v8-io12.appspot.com/#90演讲的内容,以及前后几页的相关讨论。

我碰巧参加了这次 Google I/O 演示,并随后与演讲者(V8 作者之一)进行了交谈。我一直在自己的代码中使用一种技术,该技术涉及读取数组末尾之后的内容,作为优化某个特定情况的误导性(事后看来)尝试。他证实,如果你试图甚至read超过数组末尾,它将阻止使用简单优化格式。

如果 V8 作者所说的仍然正确,那么读取超出数组末尾的内容将阻止其优化,并且必须回退到较慢的格式。

现在,V8 可能同时得到了改进,以有效地处理这种情况,或者其他 JavaScript 引擎会以不同的方式处理它。我不知道这方面的一种或另一种方式,但这种去优化正是演示文稿所讨论的内容。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么在 V8 中使用此代码片段 <= 比 < 慢? 的相关文章

随机推荐