Go - 基于逃逸分析来提升程序性能

Go语言精选

共 1854字,需浏览 4分钟

 ·

2021-10-25 21:52

文章目录:

  • 前言

  • 什么是逃逸分析?

  • 如何确定是否逃逸?

  • 可能出现逃逸的场景

    • 01

    • 02

    • 03

  • 小结

  • 推荐阅读

前言

为什么需要了解逃逸分析?

因为我们想要提升程序性能,通过逃逸分析我们能够知道变量是分配到堆上还是栈上,如果分配到栈上,内存的分配和释放都是由编译器进行管理,分配和释放的速度非常快,如果分配到堆上,堆不像栈那样可以自动清理,它会引起频繁地进行垃圾回收(GC),而垃圾回收会占用比较大的系统开销。

什么是逃逸分析?

在编译程序优化理论中,逃逸分析是一种确定指针动态范围的方法,简单来说就是分析在程序的哪些地方可以访问到该指针。

简单的说,它是在对变量放到堆上还是栈上进行分析,该分析在编译阶段完成。如果一个变量超过了函数调用的生命周期,也就是这个变量在函数外部存在引用,编译器会把这个变量分配到堆上,这时我们就说这个变量发生逃逸了。

如何确定是否逃逸?

go run -gcflags '-m -l' main.go

可能出现逃逸的场景

01

package main

type Student struct {
 Name interface{}
}

func main()  {
 stu := new(Student)
 stu.Name = "tom"

}

分析结果:

go run -gcflags '-m -l' 01.go
# command-line-arguments
./01.go:8:12: new(Student) does not escape
./01.go:9:11: "tom" escapes to heap

interface{} 赋值,会发生逃逸,优化方案是将类型设置为固定类型,例如:string

package main

type Student struct {
 Name string
}

func main()  {
 stu := new(Student)
 stu.Name = "tom"

}

分析结果:

go run -gcflags '-m -l' 01.go
# command-line-arguments
./01.go:8:12: new(Student) does not escape

02

package main

type Student struct {
 Name string
}

func GetStudent() *Student {
 stu := new(Student)
 stu.Name = "tom"
 return stu
}

func main() {
 GetStudent()
}

分析结果:

go run -gcflags '-m -l' 02.go
# command-line-arguments
./02.go:8:12: new(Student) escapes to heap

返回指针类型,会发生逃逸,优化方案视情况而定。

函数传递指针和传值哪个效率高吗?我们知道传递指针可以减少底层值的拷贝,可以提高效率,但是如果拷贝的数据量小,由于指针传递会产生逃逸,可能会使用堆,也可能会增加 GC 的负担,所以传递指针不一定是高效的。

不要盲目使用变量指针作为参数,虽然减少了复制,但变量逃逸的开销可能更大。

03

package main

func main() {
 nums := make([]int, 10000, 10000)

 for i := range nums {
  nums[i] = i
 }
}

分析结果:

go run -gcflags '-m -l' 03.go
# command-line-arguments
./03.go:4:14: make([]int, 10000, 10000) escapes to heap

栈空间不足,会发生逃逸,优化方案尽量设置容量,如果容量实在过大那就没办法了。

小结

  1. 逃逸分析是编译器在静态编译时完成的。
  2. 逃逸分析后可以确定哪些变量可以分配在栈上,栈的性能好。

以上,希望对你能够有所帮助。



推荐阅读


福利

我为大家整理了一份从入门到进阶的Go学习资料礼包,包含学习建议:入门看什么,进阶看什么。关注公众号 「polarisxu」,回复 ebook 获取;还可以回复「进群」,和数万 Gopher 交流学习。

浏览 26
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报