glolang编译器中的空函数优化
Empty function optimization in glolang compiler
golang编译器是否优化空函数?
我希望在构建产品时从 main.go 中删除调试日志代码行
main.go
func main() {
logging.DebugLog("hey %d", 123)
}
调试模式,
// +build dev
package logging
import (
"fmt"
)
func DebugLog(pattern string, args... interface{}) {
msg := fmt.Sprintf(pattern, args...)
fmt.Printf("debug: %s\n", msg)
}
生产模式,
// +build !dev
package logging
import (
"fmt"
)
func DebugLog(pattern string, args... interface{}) {}
golang编译器是否会在编译时从main函数中去掉DebugLog函数行?或者只是离开并在 运行 时间内执行?
让我详细回答一下。
答案是肯定的,至少是某个版本的golang编译器。
试验台
go版本go1.13.15linux/amd64
猫./main.go
package main
import (
"./fc"
)
func main() {
fc.Dosome()
}
cat ./fc/funcdummy.go
// +build !dev
package fc
func Dosome() {
}
cat ./fc/func.go
// +build dev
package fc
import (
"fmt"
)
func Dosome() {
fmt.Println("hello world")
}
go build -tags dev -o ./havetag ./main.go
go build -o ./notag ./main.go
go tool objdump -S ./notag > ./dumpnotag
go tool objdump -S ./havetag > ./dumphavetag
结果
grep 'Dosome' -A 5 -B 5 ./dumphavetag
0x48cf69 483b6110 CMPQ 0x10(CX), SP
0x48cf6d 7670 JBE 0x48cfdf
0x48cf6f 4883ec58 SUBQ [=14=]x58, SP
0x48cf73 48896c2450 MOVQ BP, 0x50(SP)
0x48cf78 488d6c2450 LEAQ 0x50(SP), BP
fc.Dosome()
0x48cf7d 0f57c0 XORPS X0, X0
fmt.Println("hello world")
0x48cf80 0f11442440 MOVUPS X0, 0x40(SP)
0x48cf85 488d0554120100 LEAQ 0x11254(IP), AX
0x48cf8c 4889442440 MOVQ AX, 0x40(SP)
grep 'Dosome' -A 5 -B 5 ./dumpnotag
//empty
因此,我们可以看到,优化了空函数,没有为 golang 编译器添加更多编译标志。
更多
我发现这个 issue 相关,所以你需要现代版本的 go compile。你可以得到你想要的。
We now do whole subtree inlining, and dead code elimination.
golang编译器是否优化空函数?
我希望在构建产品时从 main.go 中删除调试日志代码行
main.go
func main() {
logging.DebugLog("hey %d", 123)
}
调试模式,
// +build dev
package logging
import (
"fmt"
)
func DebugLog(pattern string, args... interface{}) {
msg := fmt.Sprintf(pattern, args...)
fmt.Printf("debug: %s\n", msg)
}
生产模式,
// +build !dev
package logging
import (
"fmt"
)
func DebugLog(pattern string, args... interface{}) {}
golang编译器是否会在编译时从main函数中去掉DebugLog函数行?或者只是离开并在 运行 时间内执行?
让我详细回答一下。
答案是肯定的,至少是某个版本的golang编译器。
试验台
go版本go1.13.15linux/amd64
猫./main.go
package main
import (
"./fc"
)
func main() {
fc.Dosome()
}
cat ./fc/funcdummy.go
// +build !dev
package fc
func Dosome() {
}
cat ./fc/func.go
// +build dev
package fc
import (
"fmt"
)
func Dosome() {
fmt.Println("hello world")
}
go build -tags dev -o ./havetag ./main.go
go build -o ./notag ./main.go
go tool objdump -S ./notag > ./dumpnotag
go tool objdump -S ./havetag > ./dumphavetag
结果
grep 'Dosome' -A 5 -B 5 ./dumphavetag
0x48cf69 483b6110 CMPQ 0x10(CX), SP
0x48cf6d 7670 JBE 0x48cfdf
0x48cf6f 4883ec58 SUBQ [=14=]x58, SP
0x48cf73 48896c2450 MOVQ BP, 0x50(SP)
0x48cf78 488d6c2450 LEAQ 0x50(SP), BP
fc.Dosome()
0x48cf7d 0f57c0 XORPS X0, X0
fmt.Println("hello world")
0x48cf80 0f11442440 MOVUPS X0, 0x40(SP)
0x48cf85 488d0554120100 LEAQ 0x11254(IP), AX
0x48cf8c 4889442440 MOVQ AX, 0x40(SP)
grep 'Dosome' -A 5 -B 5 ./dumpnotag
//empty
因此,我们可以看到,优化了空函数,没有为 golang 编译器添加更多编译标志。
更多
我发现这个 issue 相关,所以你需要现代版本的 go compile。你可以得到你想要的。
We now do whole subtree inlining, and dead code elimination.