参考:Golang内存分配逃逸分析 – jimshi – 博客园
GO语言变量逃逸分析 – Go语言中文网 – Golang中文社区
总结下,就是:
1. 堆和栈
之前写c++的时候,栈是各种局部变量,函数结束就自动释放;堆就是使用new和malloc分配的,需要rd去关注啥时候分配,啥时候释放。在栈上分配内存比较快,而且回收也快,在堆上分配就耗费的资源比较多。而且,在栈上面分配的,函数结束后就自动回收了,只有全局的栈上的变量和堆上的变量,才需要GC回收,减少堆上分配内存的同时,也减轻了gc的压力。
所以go就希望,能尽可能多的在栈上面分配资源。那go是怎么做的呢?
func F() {
temp := make([]int, 0, 20)
...
}
就比如上面这种,虽然是手动执行了make来分配内存,正常来说应该在堆上,但是实际上是在栈上面。但是也不是所有的局部变量都能分配到栈上。
func F() []int{
a := make([]int, 0, 20)
return a
}
比如上面这种,虽然是局部变量,但是因为这个局部变量作为函数返回值返回了,所以也不能分配在栈上,必须分配在堆上。这就是内存逃逸。
2. 检查内存逃逸
指令:
go build -gcflags=-m
执行的时间点:
编译的时候分析出来的,不是运行的时候
3.发生内存逃逸的几种情况
大体的原则就是,不确定要分配堆还是栈的时候,就分配到堆上,哈哈
(1)函数内分配的指针,作为函数返回值返回的时候
(2)栈空间不足的时候
package main
func Slice() {
s := make([]int, 1000, 1000)
for index, _ := range s {
s[index] = index
}
}
func main() {
Slice()
}
比如上面这种,只是分配了1000的时候,还是在栈上分配,当调整为1000*10的时候,就分配到堆上了
(3)interface:当函数的入参是interface的时候
(4)slice和map里面的元素时指针的时候
(5)闭包,这个没看懂
版权声明:本文为qq_32625545原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。