Golang逃逸分析

首先我们来看一下什么是逃逸分析

在编译程序优化理论中,逃逸分析是一种确定指针动态范围的方法——分析在程序的哪些地方可以访问到指针。它涉及到指针分析和形状分析。 当一个变量(或对象)在子程序中被分配时,一个指向变量的指针可能逃逸到其它执行线程中,或者去调用子程序。如果使用尾递归优化(通常在函数编程语言中是需要的),对象也可能逃逸到被调用的子程序中。如果一种语言支持第一类型的延续性在Scheme和Standard ML of New Jersey中同样如此),部分调用栈也可能发生逃逸。 如果一个子程序分配一个对象并返回一个该对象的指针,该对象可能在程序中的任何一个地方被访问到——这样指针就成功“逃逸”了。如果指针存储在全局变量或者其它数据结构中,它们也可能发生逃逸,这种情况是当前程序中的指针逃逸。 逃逸分析需要确定指针所有可以存储的地方,保证指针的生命周期只在当前进程或线程中。

在Go语言中,编译器能够智能的分析出一个变量是否该分配在栈上还是堆上,分配在栈上的变量能够在函数声明周期结束之后立即被销毁吗,分配在堆上的在后期可以被GC过程销毁。由此可见,分配在栈上的变量是不会增加GC的负担的。

对于go来讲,如果一个变量的引用作为函数的返回值返回,那么将发生逃逸,因为它在函数返回后,仍然可能在其他的地方被其他的对象所引用。以下是可能发生逃逸的操作:

  1. 函数调用另外的函数。
  2. 引用被赋值给结构体成员,
  3. slice和map
  4. cgo对变量的指针引用。

可以通过在编译时加上-m -l参数来进行逃逸分析,其中-m将会输出逃逸分析相关信息,-l防止编译器进行自动的方法内联。

参考资料: