关于后端:Go死码消除

40次阅读

共计 1022 个字符,预计需要花费 3 分钟才能阅读完成。

概念:

死码打消(dead code elimination, DCE) 是一种编译器优化技术, 作用是在编译阶段去掉对程序运行后果没有任何影响的代码

和 逃逸剖析, 内联优化并称为 Go 编译器执行的三个重要优化


成果:

对于 const.go代码如下:

package main

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)
    }
}

对于 var.go 代码如下:

package main

import "fmt"

func max2(x, y int) int {
    if x > y {return x}
    return y
}

var x, y = 10, 20

func main() {if max2(x, y) == x {fmt.Println(x)
    }
}

两个文件的差别, 只在于 两个参数 是变量还是常量

别离编译 const.govar.go, 生成的二进制文件大小如下:

go build -o 想要生成的二进制名称 想要编译的.go 文件

不难发现, constvar 体积小了约 10%

为何如此?

首先编译器会对 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)
    }
}

因为 ab 是常量, 永远有a<b, 编译器能够在编译时证实该分支永远不会为 true, 因而编译器能够进一步优化代码为:

if a > b {}这个分支被打消了, 这称为 分支打消

又晓得后果总是等于 b, 因而编译器还将进一步将代码优化为:

package main

const a, b = 10, 20

func main() {const result = b}

最初就是:

package main

func main() {}

而对于var.go, 参数为 全局变量 不为常量, 编译器并不知道运行过程中 x、y 会不会产生扭转, 因而不能进行死代码打消.

这部分代码被编译到最终的二进制程序中, 造成 二进制文件 varconst 体积大了约 10%

分支打消是死码打消一种. 应用动态证实来表明一段代码永远不可达, 通常会被称为死代码, 它不须要在最终的二进制文件中编译和优化.

编译器在编译阶段, 死码打消与内联优化一起工作, 能够缩小循环和分支产生的代码数量

本文由 mdnice 多平台公布

正文完
 0