go:noinline

警告
本文最后更新于 2020-12-20,文中内容可能已过时。

Go语言的Inlining是指将被调用的函数体直接嵌入到调用它的函数中,从而消除了函数调用的开销,可以提高程序的性能。Inlining可以减少函数调用的开销,减少函数的栈帧创建和销毁时间,并且在编译期间可以进行一些额外的优化。

  • 减少函数调用的开销,提高程序性能;
  • 减少函数的栈帧创建和销毁时间,提高程序性能;
  • 编译期间可以进行一些额外的优化,提高程序性能。
  • 可能会导致代码体积增大;
  • 可能会增加代码复杂度,因为在代码中插入了大量的函数体;
  • 可能会增加代码的编译时间和内存消耗。

因此,在使用Inlining时需要权衡它的优缺点,并且在实际应用中需要根据具体情况来决定是否使用Inlining。通常情况下,Inlining对于简单的函数或者短小精悍的函数是非常有用的,但是对于复杂的函数或者过长的函数,可能不太适合使用Inlining。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
func main() {
	a := 3
	b := 2
	_ = sum(a, b)
}

//go:noinline
func sum(a int, b int) int { return a + b }

// 压测函数
func Benchmark_main(b *testing.B) {
	for i := 0; i < b.N; i++ {
		main()
	}
}

压测结果,内联优化可以提高程序的性能。

1
2
3
4
# 没有noinline
Benchmark_main-16       837212241                1.336 ns/op           0 B/op          0 allocs/op
# 有noinline
Benchmark_main-16       1000000000               0.2218 ns/op          0 B/op          0 allocs/op
1
2
3
4
5
6
# 没有go:noinline指令,显示编译器做了内联优化
$ go build -gcflags "-m=2"
# demo/go
./test.go:9:6: can inline sum with cost 4 as: func(int, int) int { return a + b }
./test.go:3:6: can inline main with cost 20 as: func() { a := 3; b := 2; _ = sum(a, b) }
./test.go:6:9: inlining call to sum

相关内容