[英]Why does Array.prototype.fill() have such a large performance difference compared to a `for` loop?
In doing a little testing (Chrome on macOS) of the Array.prototype.fill()
method, its clearly almost twice as slow (if not slower) than simply creating your own for
loop and filling your array.在对
Array.prototype.fill()
方法进行一些测试(macOS 上的 Chrome)时,它显然比简单地创建自己的for
循环并填充数组慢了将近两倍(如果不是更慢的话)。
Clearly doing something like:显然在做类似的事情:
for( var i = 0; i < Array.length; i++) {
A[i] = 0;
}
vs对比
Array.fill(0);
The Array.fill()
method would take ~210-250ms to fill an array of size 10000000, while the for
loop would take ~70-90ms. Array.fill()
方法需要大约 210-250 毫秒来填充大小为 10000000 的数组,而for
循环需要大约 70-90 毫秒。 It just seems that the Array.fill()
method could be re-written to simply use a straight forward loop since you'd always know your initial index and target index.似乎
Array.fill()
方法可以重写为简单地使用直接循环,因为您总是知道初始索引和目标索引。
let arrayTest = new Array(10000000), startTime, endTime; startTime = performance.now(); arrayTest.fill(0); endTime = performance.now(); console.log("%sms", endTime - startTime); arrayTest = new Array(10000000); startTime = performance.now(); for (let i = 0; i < arrayTest.length; i++){ arrayTest[i] = 0; } endTime = performance.now(); console.log("%sms", endTime - startTime);
The above actually shows an even greater discrepancy compared to when I tested locally.与我在本地测试时相比,以上实际上显示出更大的差异。
Edit: I realize now after further testing that the discrepancies are diminished a lot when switching over to Firefox and its really engine dependent.编辑:经过进一步测试后,我现在意识到,当切换到 Firefox 及其真正依赖于引擎时,差异会减少很多。 I am guessing this is mainly a result of how different JavaScript engines are optimizing loops vs a method.
我猜这主要是 JavaScript 引擎在优化循环与方法方面有何不同的结果。 It still seems as though a loop within the
Array.prototype.fill()
could be optimized to resolve this difference though.似乎仍然可以优化
Array.prototype.fill()
中的循环来解决这种差异。
The result is consistent with reports that parts of Chrome are written in JavaScript, and rely on run time profiling and optimization to improve performance. 结果与使用JavaScript编写部分Chrome的报告一致,并依赖于运行时分析和优化来提高性能。
I packaged the test code in a function to be called repeatedly from a test page which can be loaded into different browsers (this is not a runnable snippet): 我将测试代码打包在一个要从测试页面重复调用的函数中,该测试页面可以加载到不同的浏览器中(这不是一个可运行的代码片段):
<!DOCTYPE html>
<html><head><meta charset="utf-8">
<title>Array.prototype.fill</title>
<script>
Array.prototype.customFill = function( value, start = 0, end = this.length) {
var count = end-start;
if( count > 0 && count === Math.floor(count)){
while( count--)
this[start++]=value;
}
return this;
}
function test() {
let arrayTest,
startTime,
endTime,
arraySize = 1000000;
arrayTest = new Array(arraySize);
startTime = performance.now();
for (let i = 0; i < arrayTest.length; i++){
arrayTest[i] = 0;
}
endTime = performance.now();
console.log("%sms (loop)", endTime - startTime);
arrayTest = new Array(arraySize);
startTime = performance.now();
arrayTest.fill(0);
endTime = performance.now();
console.log("%sms (fill)", endTime - startTime);
arrayTest = new Array(arraySize);
startTime = performance.now();
arrayTest.customFill(0);
endTime = performance.now();
console.log("%sms (custom fill)", endTime - startTime);
}
</script>
</head>
<body>
open the console and click <button type="button" onclick="test()">test</button>
</body>
</html>
The array size can be adjusted to suit the performance of the device used. 可以调整阵列大小以适应所用设备的性能。
The results for Chrome under Windows showed a large performance win for the loop, for the first two test clicks on test . 对于测试中的前两个测试点击, Windows下的Chrome结果显示该循环的性能大幅提升。 On the second click, timing for the loop seemed to improve.
在第二次点击时,循环的时间似乎有所改善。 On the third click both loop and fill methods appeared to be optimized and ran with nearly equal, and improved, speed.
在第三次单击时,循环和填充方法似乎都被优化并以几乎相同且改进的速度运行。 Results were repeatable after reloading the page.
重新加载页面后,结果可重复。
I find this consistent with Chrome script optimization strategies and inconsistent with Chrome's Array.prototype.fill
being written in C++ or similar. 我发现这与Chrome脚本优化策略一致,与Chrome的
Array.prototype.fill
不一致,是用C ++或类似方式编写的。 Although Array.prototype.fill.toString()
reports the function body as "native code" is doesn't say what language it is written in. 尽管
Array.prototype.fill.toString()
将函数体报告为“本机代码”,但并未说明它所使用的语言。
Added timings for a custom fill method, written for speed, and stored as Array.prototype.customFill
. 为自定义填充方法添加了时间,为速度编写,并存储为
Array.prototype.customFill
。
Timings for Firefox are consistent with Array.prototype.fill
being written in script. Firefox的
Array.prototype.fill
与使用脚本编写的Array.prototype.fill
一致。 The native implementation outperformed the loop and was generally (but not always) faster than the custom fill method. 本机实现优于循环,并且通常(但不总是)比自定义填充方法更快。
Timings for Chrome show are also consistent with Array.prototype.fill
being written in some kind of script that becomes optimized. Chrome show的
Array.prototype.fill
也与Array.prototype.fill
一致,它是用某种优化的脚本编写的。 All three fill methods tested shown an increase in speed after one or two test clicks. 测试的所有三种填充方法显示在一次或两次测试点击后速度增加。
However, the custom fill method starts out over ten times faster than Chromes native version. 但是,自定义填充方法的启动速度比Chromes本机版快十倍。 You would need to put nonsense code in the custom method to slow it down enough to approach the native method's initial speed.
您需要在自定义方法中放入无意义的代码,以便将其减慢到足以接近本机方法的初始速度。 Conversely, after optimization, the native method is around twice as fast - the custom method written in JavaScript never gets optimized to the same extent.
相反,在优化之后,本机方法的速度快了两倍 - 用JavaScript编写的自定义方法永远不会在相同的范围内进行优化。
While Chromes Array.prototype.fill
method could be written in JavaScript, additional explanation seems to be needed to account for the initial slowness and final performance optimizations noted. 虽然Chromes
Array.prototype.fill
方法可以用JavaScript编写,但似乎需要额外的解释来解释最初的缓慢和最终性能优化。
此JSPerf确认填充比for循环慢。
When array size is 1e5
, fill
always wins.当数组大小为
1e5
时, fill
总是获胜。 When array size is 1e7
, for
wins当数组大小为
1e7
时, for
wins
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.