golang内存逃逸分析

逃逸分析在编译阶段完成,目的是决定内存分配地址是栈还是堆:编译时通过 go build -gcflags=-m 可以查看逃逸对象

1、关于堆和栈 

栈可以简单理解成一次函数调用内部申请到的内存,它们会随着函数的返回把内存还给系统。

在栈上申请的内存 :函数返回直接释放,不会引起垃圾回收,对性能没有影响。

在堆上申请的对象生命周期可以超出函数调用的作用域,需要gc进行回收。

2、看几个demo

1、申请临时变量不会逃逸

func a() {
	t := make([]int, 10) // 这里是不会逃逸到堆上的
	if len(t) == 1 {
	}
}

2、函数结尾时把slice给返回了,会逃逸到堆上,因为编译器认为该对象后续会被使用

func a() []int {
	t := make([]int, 10) // 返回切片,则会逃逸
	return t
}

3、同2,返回指针和返回引用类型一样,会造成逃逸

type a struct{}

func NewA() *a {
	return &a{} // 返回指针会逃逸
}

4、因为申请空间过大的对象,也会逃逸

func a() {
	t := make([]int, 10)
	t2 := make([]int, 10000)
	if len(t) == 0 || len(t2) == 0 {

	}
}

这两个临时变量,都没有作为返回值,但我们看到t2逃逸了。这里我们知道:申请空间过大的对象,也会逃逸

5、变长空间申请,会造成逃逸

func a() {
	t := 10
	t2 := make([]int, t) // 这里还是会逃逸
	if len(t2) == 0 {
	}
}

./main.go:11:12: make([]int, t) escapes to heap
编译时发现t2又逃逸了,原因是编译器不知道需要分配多大的空间给t2,编译器其实看到的cap是变量t,而不是10

 

3、以上总结

  • 栈内存不需要gc,函数结束后回收
  • 堆上分配的内存使用完毕会交给GC处理

  • 逃逸分析在编译阶段完成,目的是决定对象分配到栈还是堆

你可能感兴趣的:(go,内存管理,golang,逃逸分析)