Go 編譯器技術死碼消消樂
一、前言
死代碼消除( dead code elimination, 縮寫 DCE )是用來移除對程序執行結果沒有任何影響的代碼,以此 減少程序的體積大小 ,並且還可以避免程序在執行過程中進行一些不必要的運算行爲,從而 減少執行時間 。
需要注意的是,除了不會執行到的代碼( unreachable code ),一些只會影響到無關程序執行結果的變量( dead variables ),也屬於死碼( dead code )的範疇。
二、舉例說明
import "fmt"
func max(a, b int) int {
if a > b {
return a
}
return b
}
const a, b = 10, 20
func main() {
if max(a, b) == a {
fmt.Println(a)
}
}
執行 go build 構建:
修改代碼:
const a, b = 10, 20
把如上代碼變更爲如下代碼:
執行 go build 構建:
對比之前,發現 const 變更爲 var 之後,編譯的文件大小變大了,爲什麼?
2.1 爲什麼編譯的文件變大?
首先編譯器會對 max 函數進行內聯優化, const.go 優化後如下:
package main
import "fmt"
const a, b = 10, 20
func main() {
var result int
if a > b {
result = a
} else {
result = b
}
if result == a {
fmt.Println(a)
}
}
對於常量 a 和 b ,編譯器在編譯時可以判斷出 a 永遠是大於 b 的,即 a > b 永遠爲 false ,也就是說 if {} 分支屬於 unreachable code 將永遠不會被執行,所以編譯器會進行第一次優化:分支消除
package main
import "fmt"
const a, b = 10, 20
func main() {
var result int
result = b
if result == a {
fmt.Println(a)
}
}
由於 result 變量後續沒有再被引用,所以 result 實際也是一個常量。相同道理,result == a 永遠爲 false ,編譯器會進行第二次分支消除優化:
package main
import "fmt"
const a, b = 10, 20
func main() {
var result int
result = b
}
對於剩下的常量則明顯屬於 dead variables ,再次優化:
package main
func main() {
}
而對於 var 定義變量, 參數爲 全局變量 不爲常量, 編譯器並不知道運行過程中 x、y 會不會發生改變, 因此不能進行死代碼消除.
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/UhwHeULIHf52xf0PMudR7Q