1. 程式人生 > 其它 >golang記憶體逃逸分析

golang記憶體逃逸分析

技術標籤:go記憶體管理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處理

  • 逃逸分析在編譯階段完成,目的是決定物件分配到棧還是堆