当前位置: 代码迷 >> JavaScript >> 为什么负数组索引要比正数组索引慢得多?
  详细解决方案

为什么负数组索引要比正数组索引慢得多?

热度:73   发布时间:2023-06-07 18:19:03.0

这是一个简单的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毫秒左右的时间。

为什么第二个循环比第一个循环快?

因为iterations[-1]计算结果是undefined (这很慢,因为它必须iterations[-1]整个原型链,并且不能采用快速路径),所以用NaN进行数学运算也总是很慢,因为这是不常见的情况。

同样,使用数字初始化iterations将使整个测试更加有用。

专家提示:如果您尝试比较两个代码的性能,最后它们都应导致相同的操作...


关于性能测试的一些一般说法:

如今,性能是编译器的工作,通过编译器优化的代码将始终比您尝试通过“技巧”进行优化的代码更快。 因此,您应该编写编译器可能会优化的代码,即在每种情况下都是其他人编写的代码 (如果这样做,您的同事也会爱上您)。 从引擎的角度来看,优化是最有益的。 因此,我会写:

 let acc = 0;
 for(const value of array) acc += value;

 // or
 const acc = array.reduce((a, b) => a + b, 0);

但是最后, 这只是一个循环 ,如果循环执行不佳,您将不会浪费很多时间,但是如果整个算法执行不佳(时间复杂度为O(n?)或更高),您将浪费很多时间。 专注于重要的事情,而不是循环。

为了详细说明Jonas Wilms的答案,Javascript不适用于否定索引(与Python等语言不同)。

iterations[-1]等于iteration["-1"] ,后者在数组对象中查找名为-1的属性。 这就是为什么iterations[-1]将评估为undefined

  相关解决方案