Golang - 内存逃逸分析
面试必问:
1、什么是内存逃逸
2、内存逃逸的场景有哪些
3、分析内存逃逸的意义
4、怎么避免内存逃逸
1、什么是内存逃逸
在了解什么是内存逃逸之前,我们先来简单地熟悉一下两个概念。栈内存和堆内存。
Golang的GC主要是针对堆的,不是栈。
值类型的全局变量分配在栈上,引用类型的全局变量分配在堆上。
局部变量内存分配可能在栈上也可能在堆上。
一个对象本应该分配在栈上面,结果分配在了堆上面,这就是内存逃逸。
2、内存逃逸的场景有哪些
分析内存逃逸的命令: go build -gcflags '-m' main.go
常见的场景有四种:局部指针返回,栈空间不足,动态类型,闭包引用。
1)、局部指针返回
当我们在某个方法内定义了一个局部指针,并且将这个指针作为返回值返回时,此时就发生了逃逸。
这种类型的逃逸是比较常见的,如下:
2)、栈空间不足
众所周知,在系统中栈空间相比与总的内存来说是非常小的。如下,我的Mac是16G*512G的,可是整个系统中栈空间大小也才8M。
而在我们的实际编码过程中,大部分Goroutine的占用空间不到10KB(这也是Golang能支持高并发的原因之一)。
而其中分配给栈的更是少之又少。所以一旦某个对象体积过大时候就会发生逃逸,从栈上面转到堆上面。
有两个map,space1和space2,space1长度大小都是100,space2长度大小都是10000,结果space2发生了逃逸,space1没有。如下:
3)、动态类型
这种内存逃逸应该是最多的,最常见的,而且还无法避免。
简单地说就是被调用函数的入参是interface或者是不定参数,此时就会发生内存逃逸。如下:
一个简简单单的Println居然也会发生内存逃逸。那么问题来了,这个是怎么导致的呢?
废话不多说,直接拔掉底裤撸源码。此处就是所谓的动态类型。
4)、闭包调用
这种场景是非常少的,一般没有人写这种可读性这么差的代码,我们只需要知道这种场景即可,大概率是碰不上的。
3、分析内存逃逸的意义
简单的总结就是两点:减轻GC的压力,提高分配速度。
前面已经提及,Golang的GC主要是针对堆的,而不是栈。
试想一下,如果大量的对象从栈逃逸到堆上,是不是就会增加GC的压力。
在GC的过程中会占用比较大的系统开销(一般可达到CPU容量的25%),而且目前所有的GC都有STW这个死结,而STW会造成用户直观的“卡顿”,非常影响用户体验。
STW:"Stop the World" 阶段,当前运行的所有程序将被暂停,扫描内存的 root 节点和添加写屏障 (write barrier)。
GC过程有两次STW:第一次STW会准备根对象的扫描,启动写屏障(Write Barrier)和辅助GC(mutator assist);第二次STW会重新扫描(rescan)部分根对象,禁用写屏障(Write Barrier)和辅助GC(mutator assist)。
此外,堆和栈相比,堆适合不可预知大小的内存分配。但是为此付出的代价是分配速度较慢,而且会形成内存碎片。栈内存分配则会非常快。栈分配内存只需要两个CPU指令:“PUSH”和“RELEASE”,分配和释放;而堆内存分配首先需要去找到一块大小合适的内存块,之后要通过垃圾回收才能释放。
通过逃逸分析,可以尽量把那些不需要分配到堆上的变量直接分配到栈上,堆上的变量少了,会减轻分配堆内存的开销,同时也会减少GC的压力,提高程序的运行速度。
4、怎么避免内存逃逸
首先需要注意的是,Golang在编译的时候就可以确立逃逸,并不需要等到运行时。这样就给了咱们避免内存逃逸的机会。另外明确一点,小编认为没有任何方式能绝对避免内存逃逸。
存在【动态类型】这种逃逸方式,几乎所有的库函数都是动态类型的。
主要的避免原则分别针对上面几种场景:
1)尽量减少外部指针引用,必要的时候可以使用值传递;
2)对于自己定义的数据大小,有一个基本的预判,尽量不要出现栈空间溢出的情况;
3)Golang中的接口类型的方法调用是动态调度,如果对于性能要求比较高且访问频次比较高的函数调用,应该尽量避免使用接口类型;
4)尽量不要写闭包函数,可读性差且发生逃逸。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」