performance - Go 运行时是否在每次迭代时评估 for 循环条件?

标签 performance go compiler-optimization

这是《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.Pi62.8318530718

Go 编译器 recently switchedSSA ,所以这些优化会不断改进,因为它们会从中受益匪浅。目前 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/

相关文章:

memory-management - 在 Go 中使用 append 进行前置的机制是什么?

arrays - 无法使用 Golang 交换二维数组 slice 的元素

c++ - C++ 中公共(public)子表达式消除的局限性

c++ - 可以优化 b&&0

performance - 正确使用 ETag

php - 在简单网站上缓存字体以防止 FOIT?

python - 加速django嵌套for循环时间序列

php - 速度 : MySQL vs File Output

web-applications - 在 Web 应用程序中使用 panic

android - 禁用 JNI C 代码中变量的编译器优化