2 回答
TA贡献1851条经验 获得超4个赞
简而言之,1/0 版本更快,因为数组的元素种类有助于if
语句完成更少的工作。
更长的版本:正如@PatrickRoberts 指出的那样,V8 会跟踪存储在数组中的值的类型。这种机制相当粗粒度,它只区分“只是整数”、“只是双打”和“任何东西”。if(array[i])
,当它知道数组只包含整数时,可以简单地与 0 进行比较以查看是否应该采用分支。没有比这更快的了。但是,如果数组包含“任何东西”(包括true
),那么根据 JavaScript 的语义,V8 必须检查加载的值是否为“真”,即在条件上下文中计算为真。相反,即检查假值,实际上更容易/更快,所以 V8 检查:false
是价值?是""
吗?它是一个数字(可能是 0)吗?它是 BigInt(可能是 0n)吗?是吗document.all
(一个特别有趣的古代特例文物)?任何其他评估为true
. 在这种特殊情况下,立即检查是“聪明的”/幸运的true
,但引擎不知道这一点,而且这种启发式方法通常不会有益。
(请注意,得出if(1)
比更快的结论是错误的if(true)
——特别重要的是条件中的值是从数组中加载的,并且该数组跟踪可能值的范围,这会影响随后需要的检查或不需要对加载的值进行。当您使用常量1
和true
时,两个评估具有相同的速度(事实上,在大多数情况下,优化编译器将完全删除它们,因为当然if(true)
是真的,duh!) .)
也就是说,您看到的大部分差异不是因为这个,因为测试在第一个循环中花费了超过 90% 的时间来填充数组。将数组从长度 0 增长到一百万意味着它的后备存储需要重复扩展,这意味着要分配一个新的后备存储并复制所有现有元素。这是另一个操作,其中纯整数元素具有速度优势:它们可以使用批量复制操作,移动数据的速度与 CPU 访问内存的速度一样快。然而,在“任何”数组中,垃圾收集器必须执行额外的传递以查看是否有任何值是它感兴趣的引用。在这种情况下,所有值都是true
哨兵,但它们不是,但 GC 不检查就无法知道。
添加回答
举报