assembly - 为什么涡扇会剥小圈?
问题描述
在编译循环时,turbofan 似乎大部分时间都在剥离第一个循环迭代。例如像这样的循环:
function fill256(int32Array) {
var i = 255;
do {
int32Array[i] = 0;
} while(--i >= 0);
}
被优化为这样的机器代码:
# rdx is int32Array
0x13f38bcef7a 5a 488b4a2f REX.W movq rcx,[rdx+0x2f]
0x13f38bcef7e 5e 488b7a3f REX.W movq rdi,[rdx+0x3f]
0x13f38bcef82 62 4c8b4237 REX.W movq r8,[rdx+0x37]
# peeled iteration
0x13f38bcef86 66 4881f9ff000000 REX.W cmpq rcx,0xff
0x13f38bcef8d 6d 0f8614010000 jna 0x13f38bcf0a7 <+0x187>
0x13f38bcef93 73 4e8d0c07 REX.W leaq r9,[rdi+r8*1]
0x13f38bcef97 77 41c781fc03000000000000 movl [r9+0x3fc],0x0 # dword store
0x13f38bcefa2 82 41b9fe000000 movl r9,0xfe
0x13f38bcefa8 88 e906000000 jmp 0x13f38bcefb3 <+0x93>
0x13f38bcefad 8d 0f1f00 nop
# loop proper
0x13f38bcefb0 90 4d8bcb REX.W movq r9,r11
# first iteration entry point:
0x13f38bcefb3 93 493b65e0 REX.W cmpq rsp,[r13-0x20] (external value (StackGuard::address_of_jslimit()))
0x13f38bcefb7 97 0f868b000000 jna 0x13f38bcf048 <+0x128>
0x13f38bcefbd 9d 458d59ff leal r11,[r9-0x1]
0x13f38bcefc1 a1 4d63e1 REX.W movsxlq r12,r9
0x13f38bcefc4 a4 4c3be1 REX.W cmpq r12,rcx
0x13f38bcefc7 a7 0f83e6000000 jnc 0x13f38bcf0b3 <+0x193>
0x13f38bcefcd ad 4e8d0c07 REX.W leaq r9,[rdi+r8*1]
0x13f38bcefd1 b1 43c704a100000000 movl [r9+r12*4],0x0 # dword store
0x13f38bcefd9 b9 4183fb00 cmpl r11,0x0
0x13f38bcefdd bd 7dd1 jge 0x13f38bcefb0 <+0x90>
这并不特定于特定的循环构造,但似乎适用于所有具有小主体的循环。V8 源代码注释只是说这是一种优化,但它实际上除了增加代码大小之外还有什么作用呢?
我知道如果引入新的不变量,剥离可能是有益的。
解决方案
似乎剥离第一次迭代是 turbofan 提升循环语句的要求。
编译器技术负责人的这个演示似乎表明剥离是一种更安全地提升代码的新方法。幻灯片 17:
循环剥离:由于激进的提升,不再有去优化循环
确实,击败剥离步骤会对性能产生巨大影响。这个:
// var buf = new Int32Array(10000);
for (var i = 0; i < 10; ++i) {
if (i === 0) continue;
for (var j = 0; j < 1000; ++j) {
if (j === 0) continue;
buf[i*j] = i ^ j;
}
}
比这慢三倍:
for (var i = 0; i < 10; ++i)
for (var j = 0; j < 1000; ++j)
buf[i*j] = i ^ j;
因为类型和范围检查buf
保留在内部循环中。
推荐阅读
- flutter - 滚动时颤动CheckboxListTile失去选中状态
- pandas - 熊猫将逐列添加到新数据框中
- python - 从 Python 调用的 C# DLL
- c++ - Unreal C++ 从 Fvector 获取 Actor 位置以浮动
- javascript - classList.remove() 比 className 字符串操作更糟糕
- django - Django 从数据库 {{ 专业 }} 翻译数据
- python - 如何在 python tkinter 上使用多个窗口
- batch-file - 将所有大空格键替换为[空格键]=[空格键]
- mysql - 根据日期子生成新表?
- scala - 火花:java ClassNotFoundException