为了账号安全,请及时绑定邮箱和手机立即绑定

为什么 if(1) 比 if(true) 快

为什么 if(1) 比 if(true) 快

MYYA 2023-01-06 10:35:16

我正在尝试用 JavaScript 和画布制作 Conway 的生命游戏,我有一个 1280x720 的矩阵,用于存储单元格数据,我目前将数据存储为 1 = alive,0 = dead,然后当我检查时如果一个细胞是活的,我只是简单地做:if(matrix[i][j]) 我很好奇这是否可以改进,并在 https://jsbench.me/上做了一些测试,复制了一个类似的场景,并注意到如果使用“true/false”,整个事情+-11% 慢,为什么会这样?不应该更快吗?


示例基准测试,只需将 1 更改为 true 即可测试其他场景


let array = []

for(let i = 0; i<1000000; i++){

   array.push(1)

}

let sum = 0

for(let i = 0; i<1000000;i++){

    if(array[i]){

        sum++

    }

}


查看完整描述

2 回答

?
隔江千里

TA贡献0条经验 获得超10个赞

您看到的性能差异并非严格归因于if语句评估,而是归因于从中访问值 (1true) 的数组元素种类。V8 引擎区分不同元素种类的数组。数组1将被视为PACKED_SMI_ELEMENTS,而数组true将被视为PACKED_ELEMENTS。因此,使用布尔元素的版本会慢一点。

作为说明,这是在数组元素种类之间应用的相对性能优化的格子,左上角的性能最佳,右下角的性能最差:

//img4.sycdn.imooc.com/63b7890a00012f7f06470336.jpg

是一个基准,将您的测试与我根据下面的评论添加的测试进行比较:

//img1.sycdn.imooc.com/63b789180001714008440640.jpg


查看完整回答
反对 回复 2023-01-06
?
繁花不似锦

TA贡献1595条经验 获得超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)——特别重要的是条件中的值是从数组中加载的,并且该数组跟踪可能值的范围,这会影响随后需要的检查或不需要对加载的值进行。当您使用常量1true时,两个评估具有相同的速度(事实上,在大多数情况下,优化编译器将完全删除它们,因为当然if(true)是真的,duh!) .)

也就是说,您看到的大部分差异不是因为这个,因为测试在第一个循环中花费了超过 90% 的时间来填充数组。将数组从长度 0 增长到一百万意味着它的后备存储需要重复扩展,这意味着要分配一个新的后备存储并复制所有现有元素。这是另一个操作,其中纯整数元素具有速度优势:它们可以使用批量复制操作,移动数据的速度与 CPU 访问内存的速度一样快。然而,在“任何”数组中,垃圾收集器必须执行额外的传递以查看是否有任何值是它感兴趣的引用。在这种情况下,所有值都是true哨兵,但它们不是,但 GC 不检查就无法知道。


查看完整回答
反对 回复 2023-01-06
  • 2 回答
  • 0 关注
  • 12 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信