让我们一起分析Go语言逃逸

1.介绍

熟悉 C / C++ 的读者朋友们应该都知道一个进程(应用程序)的虚拟内存空间划分为栈内存区和堆内存区。

我们提供的服务有:成都网站建设、网站建设、微信公众号开发、网站优化、网站认证、石嘴山ssl等。为近千家企事业单位解决了网站和推广的问题。提供周到的售前咨询和贴心的售后服务,是有科学管理、有技术的石嘴山网站制作公司

栈内存区上对象的内存空间是自动分配和销毁的,使用者无需关心。但是,堆内存区上对象的内存空间是需要使用者自己管理,无形中增加了使用者的心智负担。

因此,一些高级语言会支持垃圾回收(GC),降低使用者内存管理的心智负担。支持垃圾回收的语言可以自动管理堆内存区上对象的内存空间。

Go 语言编译器负责决定把对象分配到栈上或堆上,比如一个对象在函数退出后就不可达(没有其他对象引用该对象)时,那就将该对象分配到栈上,反之,则分配到堆上。

如果一个对象被分配到堆上,就需要 Go 的垃圾回收管理该对象的内存空间。但是,垃圾回收是有代价的,它会占用系统开销。

所以,为了更大限度地降低垃圾回收占用的系统资源,提升应用程序本身可使用的系统资源,使用者就需要尽量减少堆内存分配,尽量多地使应用程序使用栈内存分配,尽量避免 Go 编译器通过逃逸分析优化后被分配到栈内存的对象逃逸到堆内存。

2.查看对象是否发生逃逸

Go 语言工具链提供了查看对象是否逃逸的方法,我们在执行 go build 时,配合使用参数 -gcflags 开启编译器支持的额外功能,例如:

go build -gcflasg '-m -m -l' main.go

  • -m 用于输出编译器的执行细节,包括逃逸分析的执行。
  • -l 用于禁用内联优化。

我们通过使用 Go 语言工具链对一段简单的示例代码进行查看对象是否发生逃逸。

func main() {
sum(1, 2)
}

func sum(a, b int) *int {
res := a + b
return &res
}

输出结果:

go build -gcflags '-m -m -l' main.go
# command-line-arguments
./main.go:8:2: res escapes to heap:
./main.go:8:2: flow: ~r0 = &res:
./main.go:8:2: from &res (address-of) at ./main.go:9:9
./main.go:8:2: from return &res (return) at ./main.go:9:2
./main.go:8:2: moved to heap: res

阅读上面这段代码,我们发现 sum 函数中的变量 res 逃逸到堆,也就是说 Go 编译器通过逃逸分析,决定将变量 res 分配到堆空间。

3.逃逸分析的作用

Go 语言编译器通过逃逸分析优化,将对象合理分配到栈空间和堆空间。

因为栈内存分配比堆内存分配更快,所以 Go 语言在编译时通过逃逸分析优化将不会发生逃逸的对象优先分配到栈空间。

因此,不仅降低堆空间内存分配的开销,同时,也可以降低垃圾回收占用的系统资源。

4.总结

本文我们介绍 Go 语言逃逸分析,它可以帮助使用者合理分配对象的内存空间。

我们知道分配到堆内存空间的对象,会导致 Go 执行垃圾回收,而垃圾回收会占用系统资源,降低应用程序本身可使用的系统资源。

所以,我们在实际项目开发中,可以借助 Go 工具链分析对象是否会发生逃逸,尽量避免一些不必要的对象逃逸。

网站名称:让我们一起分析Go语言逃逸
当前路径:http://www.shufengxianlan.com/qtweb/news8/79508.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联