在对Array.prototype.fill()
方法进行一个小测试(macOS上的Chrome)时,它显然比简单地创建自己的for
循环并填充数组慢了近两倍(如果不是更慢的话)。
明确地做类似于:
for( var i = 0; i < Array.length; i++) {
A[i] = 0;
}
vs
Array.fill(0);
Array.fill()
方法将花费大约210- 250 ms来填充大小为10000000的数组,而for
循环将花费大约70- 90 ms。看起来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);
与我在本地测试时相比,上述结果实际上显示了更大的差异。
编辑:我现在意识到,经过进一步的测试,差异减少了很多切换到Firefox和它的真正引擎依赖。我猜这主要是不同JavaScript引擎如何优化循环和方法的结果。不过,似乎仍然可以优化Array.prototype.fill()
中的循环来解决这个差异。
4条答案
按热度按时间n3schb8v1#
结果与Chrome的部分内容是用JavaScript编写的报告一致,并依赖于运行时分析和优化来提高性能。
我将测试代码打包在一个函数中,可以从一个测试页面中重复调用,该页面可以加载到不同的浏览器中(这不是一个可运行的片段):
可以调整阵列大小以适应所使用的设备的性能。
Windows下Chrome的结果显示,循环的性能大幅提升 *,前两次测试点击测试 *。在第二次点击时,循环的时间似乎有所改善。在第三次点击时,循环和填充方法似乎都得到了优化,并且以几乎相同的速度运行,并且速度有所提高。重新加载页面后,结果可重复。
我发现这与Chrome的脚本优化策略一致,与Chrome的
Array.prototype.fill
是用C++或类似语言编写的不一致。尽管Array.prototype.fill.toString()
将函数体报告为“本机代码”,但它并没有说明它是用什么语言编写的。添加了自定义填充方法的计时,为提高速度而编写,并存储为
Array.prototype.customFill
。Firefox的计时与脚本中编写的
Array.prototype.fill
一致。本机实现优于循环,并且通常(但不总是)比自定义填充方法快。Chrome显示的时间也与
Array.prototype.fill
一致,它是以某种脚本编写的,并且经过了优化。测试的所有三种填充方法在一次或两次测试点击后显示速度增加。然而,自定义填充方法的启动速度比Chromes本机版本快十倍以上。您需要在自定义方法中放入无意义的代码,以使其足够慢,以接近本机方法的初始速度。相反,在优化之后,本地方法的速度大约是原来的两倍--用JavaScript编写的自定义方法永远不会得到相同程度的优化。
虽然Chromes
Array.prototype.fill
方法可以用JavaScript编写,但似乎需要额外的解释来解释最初的缓慢和最终的性能优化。fafcakar2#
这个JSPerf确认fill比for循环慢。
kkih6yb83#
当数组大小为
1e5
时,fill
总是获胜。当数组大小为1e7
时,for
获胜tpxzln5u4#
我已经在jsbench.me和jsperf.app中测试过了,因为jsperf.com没有停产。
这两个网站都显示
Array.fill
是最快的方法。参考链接: