Go死码消除

概念:

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

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


效果:

对于 const.go代码如下:

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代码如下:

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 优化后如下:

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,因此编译器还将进一步将代码优化为:

go 复制代码
package main

const a, b = 10, 20

func main() {
	const result = b

}

最后就是:

go 复制代码
package main

func main() {
}

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

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

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

编译器在编译阶段, 死码消除与内联优化一起工作, 可以减少循环和分支产生的代码数量

相关推荐
长栎几秒前
Java 17 的模式匹配,正在杀死访问者模式
后端
风曳丷6 分钟前
# 03|恶意文本如何一路摸到工具按钮
后端
2501_915918416 分钟前
Rust 程序抓包解密,rustls 不认系统证书的几种办法
开发语言·后端·网络协议·ios·adb·https·rust
深漂的华哥8 分钟前
Ruoyi-Vue-Plus(V5.6.2) 开发环境搭建
java·前端·spring boot·后端·spring·ruoyi
小月土星17 分钟前
构建 AI 应用的后端,最主流的选择就是 Python + FastAPI。
后端·fastapi
薛定谔的悦20 分钟前
我是被现实教育之后,才明白 Skill 到底该怎么写
后端
掘金者阿豪23 分钟前
你的服务器做过体检么?一份真实的 CentOS 高并发服务器体检与优化实录
后端
SimonKing27 分钟前
AI逆向实战:一个壁纸网站被我5分钟摸透了,你也能
java·后端·程序员
IT_陈寒36 分钟前
Vite打包时踩了个坑,static资源去哪了?
前端·人工智能·后端
学心理学的程序员37 分钟前
anydoc:Firecrawl 出的 Rust 文档转 Markdown,4ms 转换、14 种格式干翻 MarkItDown
开发语言·后端·rust·开源·firecrawl·claude code·anydoc