Javascript js中双计数器的性能增益;至于;环

Javascript js中双计数器的性能增益;至于;环,javascript,arrays,performance,benchmarking,Javascript,Arrays,Performance,Benchmarking,在研究数组分配性能时,我偶然发现了这一点,据说它显示了对于形式的循环的速度显著提高: var i, j = 0; for (i = 0; i < n; i++) { myArray[j++] = i; } var i,j=0; 对于(i=0;i

在研究数组分配性能时,我偶然发现了这一点,据说它显示了
对于形式的
循环的速度显著提高:

var i, j = 0;
for (i = 0; i < n; i++) {
  myArray[j++] = i;
}
var i,j=0;
对于(i=0;i
。。。在当前浏览器中。这种“双增量”的形式对我来说完全陌生,而且似乎很奇怪。我找不到任何关于它的讨论


多年来,由于编译器优化越来越聪明,已经警告过来自微基准的误导性数据。这是其中之一吗?为什么?如果jsperf写得不正确,我希望看到一个正确的、经过修改的jsperf,它能更准确地反映现实世界的情况。

除非JS在优化方面做得非常糟糕/奇怪,否则这种双计数器循环与单计数器循环不可能更快。从机器级的角度来看,这样的代码通常会使用两个通用寄存器,而不是一个,这两个寄存器都必须递增。差异应该非常小,通常不显著,但是单个计数器应该有轻微的性能优势

确定的唯一方法是查看最终的机器说明/拆解

使用
length
可能不像访问变量那么简单。如果是这样的话,我有点惊讶,但它可能会转化为更多的指令(例如:在最坏的情况下涉及分支)。但是在这种情况下,您仍然应该使用
i
而不是
j
并且仍然使用单个计数器循环来获得稍快的结果

值得一试的是改变测试的顺序。以前的分页/缓存相关测试中的内存可能有问题,这使得后一种双计数器测试速度更快。例如,双计数器测试之后紧接着是单计数器测试。试着按执行顺序交换这两个,看看是否会影响结果

更新 如Mark在评论中的测试所示,当避免
长度时,他使用单计数器循环可以获得更快的结果。显然,
length
确实需要比一个简单变量更多的指令,可能对于关联数组的情况,优化器无法消除一些分支。但是,如果我们用变量测试正则变量,那么单计数器循环仍然会胜过双计数器循环

微基准 由于这一主题也被提出,为什么微观基准可能有些糟糕,它们并不总是糟糕的,但也有一些与之相关的警告。我想说你的测试非常微小,因为从用户的角度看,它没有做任何有意义的事情。它创建一个数据数组,但却不处理它

如果您试图从这些测试中概括性能概念,那么这可能是不好的,首先,硬件是一台动态机器。它试图预测您正在做什么,哪些代码分支更容易执行,将DRAM传输到缓存,等等。操作系统也是动态的,动态分页内存。考虑到环境的动态特性,您可能会面临编写一个微测试的危险,该测试看起来更快,但只不过是因为这些动态因素而幸运而已。做更多工作的现实世界测试,也许更重要的是,做各种工作的现实世界测试,倾向于缓解“动态运气”因素,这种因素可能会误导你,让你相信某些东西通常更快,而对于你非常具体的测试,它可能更快。您不必编写全面的大规模应用程序,就可以获得类似于现实世界的东西。例如,计算一个Mandelbrot集合是相当简单的代码(可以放在一个页面中),但仍足以避免这些微观层面的危险

另一个危险是优化编译器。当优化器检测到您基本上没有造成任何全局副作用时,您可能会被微基准测试所困扰(例如:只计算数据以丢弃数据,而不打印数据或使用数据做任何事情以在其他地方引起更改)。使用非常复杂的优化器,他们可以检测何时可以跳过某些计算,因为它们不会产生任何副作用。有时,您可能会发现,您所做的某些事情使事情运行速度加快了10000倍,但这并不是因为实际工作做得更快,但因为优化器认为根本不需要这样做,所以直接跳过了它。如果在测试中,您设身处地为用户着想,并且能够合理解释为什么可以跳过代码的某些部分,并且仍然可以在不等待太长时间的情况下为用户提供相同的输出/结果,那么优化器也可以跳过该代码。每当您针对一个强大的优化器进行微基准测试时,发现一个结果似乎太好而不真实,它可能太好而不真实,优化器只是直接跳过了这项工作,因为它在您的表面测试中注意到它实际上不需要这样做


最后但并非最不重要的一点是,专注于微观效率往往会让你陷入那种组装式思维。当您只是在一个紧密的循环中重复测试一些指令时,就没有回旋余地以更智能的方式进行优化。通常,在关注性能度量时,您希望有更多的回旋余地,从粗略的优化(算法、多线程等)到最小的微优化。当你的测试是微型的时,你最终会马上想到最细粒度的金属刮削思维,这可能会导致一种不健康的痴迷,过度地节省几个时钟周期,而现实世界可能会给你提供一个机会,用同样的努力/时间来节省数十亿美元。

我真的不知道你在问什么。您是否在问为什么使用
myArray[j++]=i
而不是
myArray[i]=i
?如果是,请说