【Go专家编程——内存管理——逃逸分析】

逃逸分析

逃逸分析(Escape Analysis)是指由编译器决定内存分配的位置,不需要程序员决定。

  • 在函数中申请一个新的对象
    • 如果分配在栈上,则函数执行结束后可自动将内存回收
    • 如果分配在堆上,则函数执行结束后可交给GC(垃圾回收)处理
  • 有了逃逸分析,返回函数局部变量变得可能
  • 逃逸分析还跟闭包息息相关

1.逃逸策略

在函数中申请新对象时,编译器会根据该对象是否被函数外部引用来决定是否逃逸:

  • 如果函数外部没有引用,则优先放到栈中
  • 如果函数外部存在引用,则必定放到堆中
  • 注意点:对于仅在函数内部使用的变量,也有可能放入堆中,如内存过大超过栈的存储能力。

2. 逃逸场景

我们可以通过编译参数-gcflags=-m来查看编译过程中的逃逸分析过程

例如go build -gcflags=-m

2.1 指针逃逸

go 复制代码
type Student struct {
	Name string
	Age int
}

func StudentRegister(name string,age int) *Student{
	s := new(Student)	// 局部变量s逃逸到堆中
	s.Name = name
	s.Age = age
	return s
}
func main(){
	StudentRegister("Jim", 18)
}

函数StudentRegister()内部的s为局部变量,其值通过函数返回值返回,s本身为一个指针,其指向的内存地址不会是栈而是堆。

2.2 栈空间不足逃逸

go 复制代码
func Slice(){
	s := make([]int,1000,1000)
	for index,_ := range s{
		s[index] = index
	}
}
func main(){
	Slice()
}

Slice函数分配了一个长度为1000的切片,是否逃逸取决于栈的空间是否足够大。

当切片长度不断增加到10000时就会发生逃逸

  • 实际上当栈的空间不足以存放当前对象或无法判断当前切片长度时会将对象分配到堆中

2.3 动态类型逃逸

很多函数的参数为interface类型,比如fmt.Println(a ...interface{}),编译期间很难确定其参数具体类型,也会产生逃逸。

go 复制代码
func main(){
	s := "Escape"
	fmt.Println(s) 
}

2.4 闭包引用对象逃逸

go 复制代码
func Fibonacci() func() int {
	a,b := 0,1
	return func() int {
		a, b = b,a+b
		return a
	}
}

func main(){
	f := Fibonacci()
	for i:=0;i<10;i++{
		fmt.Printf("Fibonacci: %d\n",f())
	}
}

该函数返回一个闭包,闭包使用了函数的局部变量a,b,使用时通过该函数获取闭包,然后每次执行闭包都会一次输出Fibonacci数列。

Fibonacci()函数中原本属于局部变量的a和b由于闭包的引用,不得不将两者放到堆上,以至于产生了逃逸。

3. 小结

  • 栈上分配内存比在堆上分配内存有更高的效率
  • 栈上分配的内存不需要GC处理
  • 堆上分配的内存使用完毕会交给GC处理
  • 逃逸分析的目的是决定分配地址是栈还是堆
  • 逃逸分析在编译阶段完成
相关推荐
mldong4 小时前
C# 开发者也有自己的轻量工作流引擎了:NuGet 装包,5 分钟跑通一条审批流
后端·c#·.net
kruptos5 小时前
分布式系统怎么“选主“?Raft 共识一次讲清
开发语言·分布式·php·共识算法
吴声子夜歌5 小时前
ApacheCommons——commons-cli(命令行参数解析)
java·开发语言·apache
爱学堂IT分享6 小时前
鹤翔老师pmp项目管理培训认证考试课 (直播录播题库送学时证明)【共58课时】-51CTO学堂
后端
benchmark_cc6 小时前
REST API 和 Python SDK 应该怎么选?量化交易数据接口选型实战
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
王的宝库6 小时前
Go 项目结构:从单文件到标准工程布局
开发语言·后端·golang
Tairitsu_H6 小时前
[C++] 深入理解红黑树:封装set与map
开发语言·c++·set·map·红黑树·模拟实现
泡海椒6 小时前
JQuick-Curl 性能分析:并发场景下的性能表现与调优,第三方接口调用不只要快写也要稳跑
java·开发语言·okhttp
小智老师PMP6 小时前
2026深度解析|PMP第八版与NPDP核心侧重点本质区别(管理类证书怎么选)
开发语言·分布式·算法·职场和发展·产品经理
花酒锄作田7 小时前
Go - Gin中使用sessions
golang