golang逃逸分析

逃逸分析是编程中的一个重要概念,用于确定对象内存分配的位置,是栈还是堆。理解逃逸分析有助于优化内存使用,减少垃圾回收开销。在Go语言中,通过`-m -l`编译标志可以查看逃逸分析信息。例如,当局部变量作为指针返回或动态类型分配时,可能发生逃逸。逃逸分析影响内存分配,如大对象分配可能会直接到堆上,而局部变量可能保留在栈中。了解这些原理能帮助开发者更好地控制程序的性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先我们先要了解一下
什么是逃逸分析?
在维基百科中有这样说明:

在编译程序优化理论中,逃逸分析是一种确定指针动态范围的方法——分析在程序的哪些地方可以访问到指针。它涉及到指针分析和形状分析。

为什么要了解逃逸分析?
我们需要了解在编程语言中内存的分配主要是分为堆和栈,虽然堆和栈的分配主要在编译过程由编译器帮我们自动完成,但是了解逃逸分析,对于内存的分配和释放原理,还有在使用过程到底是用值类型还是引用类型是非常有帮助的。

堆和栈

在了解逃逸分析之前,我们需要了解什么是堆和栈?
在我理解,堆和栈是内存存储的一种结构

  • 堆(heap) 用于动态分配内存,由程序员申请分配和释放,在go里面内存是自动回收的,有自己的一套垃圾回收机制(gc),gc的好处在于不必过多关注于内存的管理引发的一系列内存泄漏的问题,但不好也在于gc也伴随着性能的消耗。
  • 栈(stack)栈是一种线性的存储结构,栈区的内存一般由编译器分配和释放,一般存储着函数的入参以及局部变量,这些参数和局部变量会随着整个函数生命周期结束而被销毁。

栈在分配和回收内存的开销很低,只需要2个CPU指令:PUSH和POP,而堆方面一个很大的开销在于垃圾回收。

逃逸分析的例子

什么时候会发生逃逸?
继续引用维基百科的说明:

如果一个子程序分配一个对象并返回一个该对象的指针,该对象可能在程序中被访问到的地方无法确定——这样指针就成功“逃逸”了。如果指针存储在全局变量或者其它数据结构中,因为全局变量是可以在当前子程序之外访问的,此时指针也发生了逃逸。

go逃逸分析命令

go run -gcflags "-m -l" (-m打印逃逸分析信息,-l禁止内联编译)

需要空间过大逃逸

package main

func MakeSlice() {
	s := make([]int, 9000, 9000)
	s[0] = 1
}

func main() {
	MakeSlice()
}
$ go run -gcflags "-m -l" main.go
# command-line-arguments
.\main.go:4:11: make([]int, 9000, 9000) escapes to heap

指针逃逸

当局部变量在函数作为指针返回,指针可能被外部引用的时候会发生逃逸.

package main

type User struct{
	name string
}

func GetUser(name string)*User{
	return &User{name: name}
}

func main() {
	user := GetUser("张三")
	user.name = "李四"
}
$ go run -gcflags "-m -l" main.go
# command-line-arguments
.\main.go:7:14: leaking param: name
.\main.go:8:9: &User literal escapes to heap

动态类型逃逸

package main

type User struct{
	name string
}

func GetUser(name string)interface{}{
	return User{name: name}
}

func main() {
	var name = "张三"
	GetUser(name)
}

闭包逃逸

package main

func Increase() func() int {
	n := 0
	return func() int {
		n++
		return n
	}
}

func main() {
	in := Increase()
	in() // 1
	in() // 2
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值