概念
正常情况下对象在栈上分配内存,有些情况下会对象会在堆上分配内存,这就是逃逸。
go语言在一定程度消除了堆和栈的区别,go在编译的时候进行逃逸分析来决定一个对象放栈上还是放堆上,其中不逃逸的对象放栈上,可能逃逸的放堆上,分析的过程就是逃逸分析
逃逸分析时不止分析对象内存分配位置,也会做同步消除,如果你定义的对象的方法上有同步锁,但在运行时,却只有一个线程在访问,此时逃逸分析后的机器码,会去掉同步锁运行。
产生原因
- 变量共享
栈帧所在内存在栈帧结束后(return)变为不可访问区域,如果要栈帧中一些局部数据变量后扔有访问需求,需要将变量变为共享,具体的方法是返回局部变量的指针, 这样变量便会在堆上分配内存,后续可有效访问该块内存,达到共享的目的。
简而言之,任何时候,一个值被分享到函数栈帧范围之外,它都会在堆上被重新分配(逃逸)
拓展知识
对象在堆栈上有什么差异
- 栈的分配比堆快,性能好
- 在栈上分配对象最大的好处是可以减少gc的压力,不逃逸的对象分配在栈上,当函数返回时就回收了资源,不需要gc标记清除。
- 保持在栈上的值,减少了 GC 的压力。但是需要存储,跟踪和维护不同的副本。将值放在堆上的指针,会增加 GC 的压力。然而,也有它的好处,只有一个值需要存储,跟踪和维护。最关键的是如何保持正确地、一致地以及均衡(开销)地使用。
源码
|
|
编译器报告
|
|