【golang】内存逃逸常见情况和避免方式
2020-06-06 本文已影响0人
dongzd
为什么要尽量避免内存逃逸?
因为如果变量的内存发生逃逸,它的生命周期就是不可知的,其会被分配到堆上,而堆上分配内存不能像栈一样会自动释放,为了解放程序员双手,专注于业务的实现,go实现了gc垃圾回收机制,但gc会影响程序运行性能,所以要尽量减少程序的gc操作。
常见内存逃逸情况
1、在方法内把局部变量指针返回,被外部引用,其生命周期大于栈,则溢出。
2、发送指针或带有指针的值到channel,因为编译时候无法知道那个goroutine会在channel接受数据,编译器无法知道什么时候释放。
3、在一个切片上存储指针或带指针的值。比如[]*string,导致切片内容逃逸,其引用值一直在堆上。
4、因为切片的append导致超出容量,切片重新分配地址,切片背后的存储基于运行时的数据进行扩充,就会在堆上分配。
5、在interface类型上调用方法,在Interface调用方法是动态调度的,只有在运行时才知道。
如何避免
1、go语言的接口类型方法调用是动态,因此不能在编译阶段确定,所有类型结构转换成接口的过程会涉及到内存逃逸发生,在频次访问较高的函数尽量调用接口。
2、不要盲目使用变量指针作为参数,虽然减少了复制,但变量逃逸的开销更大。
3、预先设定好slice长度,避免频繁超出容量,重新分配。