讨论内存逃逸前,先了解什么是栈内存和堆内存。
一个对象应该分配在栈上面,结构分配在了堆上面,就是内存逃逸。
内存分配中的堆和栈
- 在栈上分配(静态内存分配),一般由系统进行申请和释放,eg.函数的入参、局部变量、返回值等,每个函数都会分配一个栈帧,在函数运行结束后进行销毁
- 在堆上分配(动态内存分配),在函数运行结束后仍然可以使用,如果要回收掉,需要进行GC,带来额外的性能开销
golang查看内存逃逸
1.指针逃逸
函数返回值为局部变量的指针,函数虽然退出了,但因为指针的存在,指向的内存不能随着函数结束而回收,因此只能分配在堆上
2.栈空间不足
3.变量大小不确定
4.动态类型
动态类型就是编译期间不确定参数的类型、参数的长度也不确定的情况下就会发生逃逸。
空接口interface{}可以表示任意的类型
如果函数参数为interface{},编译期间很难确定其参数的具体类型,也会发生逃逸
5.闭包引用对象
闭包函数中局部变量i在后续函数是继续使用的,编译器将其分配到堆上
总结:
1.栈上分配内存比堆中分配内存效率更高
2.栈上分配的内存不需要GC处理,而堆需要
3.逃逸分析目的是决定内存分配地址是栈还是堆
4.逃逸分析在编译阶段完成
无论变量大小,只要是指针变量都会在堆上分配,所以对于小变量使用传值(而不是传指针)效率更高