什么是内存逃逸
内存逃逸,简单来说,就是相比于某些对象,生命周期更长,无法相对于短生命周期对象那样快速回收,可能会造成一定的gc压力。
为什么存在内存逃逸
golang协程初始化时会分配一个栈,与java不同,如果一个对象的生命周期不会大于当前栈帧,该对象就不会在堆上进行分配,而是直接在栈上进行分配,在栈帧出栈时对象则会自动回收。 而内存逃逸也就是本地变量的生命周期范围大于一个栈帧,则发生了内存逃逸,简单的说:
- 栈帧在入栈是需要明确其大小,无法明确分配空间的对象都会分配到堆上
- 栈帧在函数结束时出栈,所以在函数结束时仍存在的对象需分配到堆上
需要注意的内存逃逸
- interface入参,因为golang编译器无法在编译期确定interface的类型,所以也就无法为其分配栈空间而分配到堆上
- 发送指针到channel中,因为指针逃逸到其他协程
- slice空间扩展,因为在栈帧入栈时已确定栈帧的空间大小,所以运行时slice的扩展需要分配到堆上
- 带指针的值
- 变量返回指针