这是《The Go Programming Language》一书中的一段代码:
for t := 0.0; t < cycles*2*math.Pi; t += res {
...
}
看来for循环条件中的表达式t < cycles*2*math.Pi
必须在 for 循环的每次迭代之前进行评估。或者,编译器是否通过预先计算表达式的结果来优化它(假设在迭代期间没有任何变量发生变化)?上述编码风格会影响性能吗?
最佳答案
这确实取决于 Go 版本,但 go version go1.7 windows/amd64
似乎确实计算了一次该值。
去代码:
var cycles = 10.0
var res = 1000.0
for t := 0.0; t < cycles*2*math.Pi; t += res {
}
汇编代码:
movsd [rsp+58h+var_20], xmm0
mov [rsp+58h+var_18], 0
mov [rsp+58h+var_10], 0
lea rax, qword_494500
mov [rsp+58h+var_58], rax
lea rax, [rsp+58h+var_20]
mov [rsp+58h+var_50], rax
mov [rsp+58h+var_48], 0
call runtime_convT2E
mov rax, [rsp+58h+var_40]
mov rcx, [rsp+58h+a] ; a
mov [rsp+58h+var_18], rax
mov [rsp+58h+var_10], rcx
lea rax, [rsp+58h+var_18]
mov [rsp+58h+var_58], rax
mov [rsp+58h+var_50], 1
mov [rsp+58h+var_48], 1
call fmt_Println
movsd xmm0, cs:$f64_408f400000000000
movsd xmm1, [rsp+58h+t]
addsd xmm0, xmm1
movsd [rsp+58h+t], xmm0
movsd xmm1, cs:$f64_404f6a7a2955385e
ucomisd xmm1, xmm0
ja loc_401083
f64_404f6a7a2955385e
是一个预先计算的 double 值,等于 10 * 2 * math.Pi
或 62.8318530718
Go 编译器 recently switched至 SSA ,所以这些优化会不断改进,因为它们会从中受益匪浅。目前 SSA 仅适用于 amd64:
Compiler Toolchain
This release includes a new code generation back end for 64-bit x86 systems, following a proposal from 2015 that has been under development since then. The new back end, based on SSA, generates more compact, more efficient code and provides a better platform for optimizations such as bounds check elimination.
1.8 should have it for all supported architectures :
Compiler Toolchain
Go 1.7 introduced a new compiler back end for 64-bit x86 systems. In Go 1.8, that back end has been developed further and is now used for all architectures.
关于performance - Go 运行时是否在每次迭代时评估 for 循环条件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41327984/