逃逸分析是什么?

逃逸分析是指对源代码分析,然后对内存管理进行优化和简化的过程。这个过程将决定一个变量是分配在堆上还是栈上。

逃逸分析有什么用?

它可以将变量合理的分配到它该去的地方。合理是指按需分配。举一个例子,在 Go 语言中,new 函数在函数中申请内存,退出函数后假如没有使用了,那变量应该分配到栈上;反之,一个变量,在函数之外还有引用,那就分配到堆上。

堆和栈相比,堆适合不可预知大小的内存分配,代价是分配速度较慢,而且会产生内存碎片,堆分配还需要找到大小合适的内存块,之后通过垃圾回收才能释放。栈内存分配非常快,会被自动释放。

逃逸分析,尽量把不需要分配到堆上的变量分配到栈上,减少垃圾回收机制的压力(因为堆的清理需要垃圾回收机制,频繁垃圾回收,会占用比较大的系统开销),提高运行速度。

逃逸分析是怎么完成的?

通过编译器完成。编译器分析源代码的特征以及源代码的生命周期,根据以下的规则判断变量分配到堆上或是栈上。

  1. 变量在函数外没有引用,优先分配到栈上。
  2. 变量在函数外存在引用,必定分配到堆上。
    第一条规则,并不是一定放到栈上,例如申请内存过大,超过了栈的存储能力。

如何查看是否发生逃逸?

go build -gcflags '-m-l' main.go

gcflags参数启用编译器支持。

  • -m输出编译器优化细节。
  • -l禁用内联优化,防止内联抹除逃逸被编译器。

编译期间很难确定参数具体类型,这会引起意想不到的变量逃逸,可以通过反汇编命令来查看:

go tool compile -S main.go