Golang的逃逸分析

數據智能相依偎 2024-03-22 21:38:53
逃逸分析逃逸分析(Escape Analysis)指的是將變量的內存分配在合適的地方(堆或者棧)。 在函數中申請內存有2種情況: - 如果內存分配在棧(stack)上,當函數退出的時候,這部分內存會自然的回收,不需要垃圾回收(GC,Garbage Collection) - 如果內存分配在堆(heap)上,函數的執行會交給GC(Garbage Collection)來處理。 此外,Golang與閉包密切相關。 Golang的逃逸分析Golang的逃逸分析的基本原則是:如果函數返回了變量的引用,那麽這個變量就會逃逸。 編譯器通過分析代碼,決定變量分配的地方: - 如果變量在函數外沒有被引用,那麽優先分配在棧(stack)上。 - 如果變量在函數外被引用,那麽優先分配在堆(heap)上。 需要注意的是,沒有在函數外被引用的變量,也有可能被分配在堆(heap)上。例如,這個變量需要的內存太大,超出了棧的容量,(目前,一個Goroutine的棧的最大容量,在64位系統是1GB,在32位系統是250MB)。棧內存的分配和回收是非常快速的,只需要2條CPU指令,PUSH 和 RELEASE。而堆內存,分配需要找到合適大小的內存塊,回收則是通過GC。 因此,通過內存的逃逸分析,可以嘗試將不必要分配在堆上的變量分配在棧上,減少分配堆內存的開銷和GC的壓力。下面看一下一些逃逸的例子。 指針逃逸看下面的代碼cat.go。 package maintype Cat struct { Name string Age int}//go:noinlinefunc NewCat(name string, age int) *Cat { c := new(Cat) // c will excape to heap c.Name = name c.Age = age return c}func main() { NewCat("Tom", 5)}進行逃逸分析 $ go build -gcflags="-m" cat.go# command-line-arguments./cat.go:16:6: can inline main./cat.go:9:13: leaking param: name./cat.go:10:10: new(Cat) escapes to heap可以看到,./cat.go:10:10: new(Cat) escapes to heap, 有變量的內存逃逸。 動態類型逃逸package mainimport "fmt"func test() *int { s := 3 return &s}func main() { x := test() fmt.Println(*x)}編譯代碼 $ go build -gcflags="-m -l" dynamic.go# command-line-arguments./dynamic.go:6:2: moved to heap: s./dynamic.go:11:13: ... argument does not escape./dynamic.go:11:14: *x escapes to heap變量s産生了內存逃逸,正如前一個例子。 這裏要注意的是,/dynamic.go:11:14: *x escapes to heap也發生了內存逃逸,這是因爲fmt.Println(a ...interface{}),fmt接受的參數是interface{},這是類型不確定的。 編譯期間不能確定參數的具體的類型,逃逸就會産生。 slice,map和channel的指針引用package mainfunc main() { a := make([]*int, 1) b := 12 a[0] = &b c := make(map[string]*int) d := 14 c["aaa"] = &d e := make(chan *int, 1) f := 15 e
0 阅读:1

數據智能相依偎

簡介:感謝大家的關注