安得倚天抽宝剑——Go中new到底在堆还是栈中分配

安得倚天抽宝剑——Go中new到底在堆还是栈中分配

逃逸分析是什么?

在C/C++中,我们是使用malloc或new来从堆山取一块内存,怎么使用这块内存,完全取决于程序员,因此很容易发生内存泄漏。而Go语言会在两个地方给变量分配内存,虽然Go也是可以通过new来给变量分配内存,但是分配的这块内存,可能在堆上,也可能在栈上。从性能的角度出发,在栈上分配内存和在堆上分配内存,性能差异是非常大的。因此一个变量是在对上分配内存,还是在栈上分配内存,是需要编译器经过逃逸分析才能得出结论。

在编译原理中,分析指针动态范围的方法称为逃逸分析。当一个对象的指针被多个方法或线程引用时,我们称这个指针发生了逃逸。

在这里插入图片描述

逃逸分析存在的意义何在?

其实逃逸分析并不是专属于Go的“蜜糖”,Java也使用逃逸分析。

但是Java的逃逸分析有很多限制,对于不进行全局转义的对象,Java不会将堆分配替换为堆栈分配。然而,Java使用了另一种称为标量替换的技巧,它避免了将对象放在栈上的需要。本质上,它分解对象,并将其基本成员放在栈上。

Go的GC,让程序员可以不理解堆和栈也可以编写高效的业务,让编译器去和堆和栈打交道就行了…

使用逃逸分析后,如果编译器发现这个变量在该函数结束后不会再调用了,就会把这个变量分配到栈上,毕竟使用栈速度快、不会产生内存碎片。如果编译器发现某个变量在函数之外还有其他地方要引用,那么就把这个变量分配到栈上。

为什么不将变量全部分配到堆空间上呢?像C那样不是也挺好的吗?

这是因为堆不能像栈那样函数一结束就自动清理,会导致GC频繁工作,而通过逃逸分析,我们可以尽可能把变量分配到栈上,可以减少内存碎片,减少GC回收的时间,所以逃逸分析是Go用来减少GC压力的一个技巧。

image-20220825140109870

Golang的逃逸分析怎么实现,方法和操作是怎样?

Golang的逃逸分析简单来说就是,如果一个变量的引用从声明它的函数中返出去了,则发生“逃逸”,因为它有可能在函数外被别的内容使用,所以必须分配到堆上。如果变量在函数外部没有被引用,那么就优先将这个变量放置在栈上。不过有如下几种特殊情况:

  • 函数调用其他函数
  • 引用作为结构体的成员变量
  • 切片和映射
  • Cgo指向变量的指针

还有一种情况,如果栈已经满了,或者放不下,自然只能放在堆上了。

参考资料

机械工业出版社《Go程序员面试笔试宝典》

Go并不需要Java风格的GC https://robberphex.com/go-does-not-need-a-java-style-gc/?utm_source=segmentfault&utm_medium=head

详解二:Go 语言机制之逃逸分析 https://zhuanlan.zhihu.com/p/137536970

Golang逃逸分析 https://www.jianshu.com/p/670ba8ed0685/

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ReganYue

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值