go 逃逸分析
看逃逸分析首先要知道清楚堆和栈的概念
堆和栈
堆
存储全局变量、占用内存比较大的局部变量。
人为干预的,手动申请、分配和释放
堆的内存没有特定的结构和大小,可以根据需要进行调整。
堆是进程级别的。开销会比较大,对于go这种带GC的语言来说,也会增加gc压力,同时也容易造成内存碎片。
堆分配内存的时候需要先找到一个大小合适的内存块,最后通过垃圾回收进行释放
栈
存储局部变量、返回值、函数参数这些数据
由编译器进行管理,因此栈的分配和回收的速度非常快
栈的内存通过命令 PUSH 和 RELEASE 来进行分配和释放
什么是逃逸分析
一句话:自动决定变量分配到堆还是栈
所谓逃逸就是一个对象被对个指针引用,当函数退出后,变量还在其他地方引用,就是发生了逃逸。像这种容易逃逸的对象我们会把他分配到堆上。反之,函数退出后,变量就不在使用了,我们称为未发生逃逸,把他分配到栈上。
为什么需要逃逸分析
go是自带gc的。我们不需要管理内存的释放,但是合理的分配内存能让我们的gc压力更小
- 减少gc压力,栈上的变量,函数退出后系统直接回收,不需要gc进行标记清除
- 减少内存碎片的产生
- 对堆内存分配的开销是比较大的,合理分配堆和栈能够提高程序的运行速度
go 逃逸分析的过程
一句话:函数返回一个变量的引用,则发生逃逸
简单来说就是:编译器会根据变量是否被外部引用来决定是否逃逸:
1、如果函数外部没有引用,则优先放到栈中;
2、如果函数外部存在引用,则必定放到堆中;
如何查看逃逸分析
go build -gcflags '-m -l' main.go
加-l是为了不让foo函数被内联
总结
- 在堆上进行动态内存的分配比在栈上进行内存分配,代价要大得多。
- 变量分配在栈上,需要在编译器就确定他的作用域
- 不要盲目使用变量的指针作为函数参数,虽然会减少复制操作。但其实当参数为变量自身时候,复制是在栈上完成的操作,开销远比变量逃逸后动态的在堆上分配内存少的多。
442

被折叠的 条评论
为什么被折叠?



