这是一个简单的JavaScript性能测试:
const iterations = new Array(10 ** 7);
var x = 0;
var i = iterations.length + 1;
console.time('negative');
while (--i) {
x += iterations[-i];
}
console.timeEnd('negative');
var y = 0;
var j = iterations.length;
console.time('positive');
while (j--) {
y += iterations[j];
}
console.timeEnd('positive');
第一个循环从10,000,000向下计数到1,并在每次迭代中使用负索引访问长度为1000万的数组。因此它从头到尾遍历整个数组。
第二个循环从9,999,999向下计数到0,并在每次迭代时使用正索引访问同一数组。因此它反向通过数组。
在我的PC上,第一个循环需要6秒钟以上的时间才能完成,但是第二个循环只需要400毫秒左右的时间。
为什么第二个循环比第一个循环快?
答案 0 :(得分:5)
因为iterations[-1]
的求值结果为undefined
(这很慢,因为它必须沿着整个原型链进行,并且不能走快速路径),所以也要对NaN
进行数学运算总是很慢,因为这是不常见的情况。
还用数字初始化iterations
将使整个测试更加有用。
专业提示:如果您尝试比较两个代码的性能,则它们最后都应该导致相同的操作...
关于性能测试的一些常用字眼:
性能是当今编译器的工作,由编译器优化的代码将始终比您尝试通过某些“技巧”优化的代码快。因此,您应该编写编译器可能会优化的代码,即在每种情况下,其他人编写的代码(如果这样做,您的同事也会喜欢您)。从引擎的角度来看,优化是最有益的。因此我会写:
let acc = 0;
for(const value of array) acc += value;
// or
const acc = array.reduce((a, b) => a + b, 0);
但是最终这只是一个循环,如果循环执行不佳,您不会浪费很多时间,但是如果整个算法执行不佳,您将浪费很多时间(时间复杂度O(n²)或者更多)。专注于重要的事情,而不是循环。
答案 1 :(得分:1)
要详细说明Jonas Wilms的答案,Javascript不适用于否定索引(与Python等语言不同)。
iterations[-1]
等于iteration["-1"]
,后者在数组对象中查找名为-1的属性。这就是iterations[-1]
的评估结果为undefined
的原因。