Golang逃逸分析

逃逸分析

逃逸分析是指由编译器决定内存分配的位置,不需要程序员指定,不逃逸的放栈上,可能逃逸的都要放在堆上,在函数中申请一个新的对象:

  1. 如果分配在栈中,则函数执行完成后自动将内存进行回收
  2. 如果分配在堆中,则函数执行完成之后可交给垃圾回收器进行回收

栈和堆

应用程序在运行时只会存在一个堆,程序运行器将可以主动从堆上申请内存,这些内存通过Go的内存分配器分配,并由垃圾收集器回收,栈是每个goroutine独有的,这就意味着栈上的内存操作是不需要加锁的。而堆上的内存,有时需要加锁防止多线程冲突。对于程序堆上的内存回收,还需要通过标记清除阶段,例如Go采用的三色标记法。但是,在栈上的内存而言,它的分配与释放非常廉价。简单地说,它只需要两个CPU指令:一个是分配入栈,另外一个是栈内释放。而这,只需要借助于栈相关寄存器即可完成。

逃逸规则

Go语言虽然没有明确说明逃逸分析规则,但是有以下几点准则,是可以参考的。

  • 逃逸分析是在编译器完成的,这是不同于jvm的运行时逃逸分析;
  • 如果变量在函数外部没有引用,则优先放到栈中;
  • 如果变量在函数外部存在引用,则必定放在堆中;

逃逸场景

  1. 指针逃逸:局部变量作为一个指针,其指向的内存地址不会是栈而是堆
  2. 栈空间不足逃逸:栈空间不足以存放当前对象或者无法判断当前切片长度时会将对象分配到堆中
  3. 动态类型逃逸:函数的参数未interface类型,编译期间很难确定参数的具体类型,也会产生逃逸
  4. 闭包引用对象逃逸:由于闭包的引用,不得不将其放到堆中,以至于产生逃逸

结论

  • 栈上分配的内存比堆中更有效率
  • 栈上分配的内存不需要GC处理
  • 堆上分配的内存使用完毕后交给GC处理
  • 逃逸分析的目的是决定分配的地址是栈还是堆
posted @ 2021-08-26 15:01  _Koln  阅读(184)  评论(0)    收藏  举报