当前位置:网站首页>Golang 垃圾回收机制详解
Golang 垃圾回收机制详解
2022-08-02 14:10:00 【星星泡个饭】
一、垃圾回收概念
有些编程语言(C、C++)需要手动释放那些不再需要的、分配在堆上的数据,这叫做“手动垃圾回收”,但是如果数据释放过早,后续对数据的访问就会出错,因为被释放的内存可能已经被清空或者重新分配;如果忘记释放,数据会一直占用内存,出现“内存泄漏”,所以越来越多的编程语言支持“自动垃圾回收”。
由运行时识别不再有用的数据并释放他们占用的内存,内存何时被释放,被释放的内存何时处理都不需要我们考虑
二、常用的垃圾回收算法
引用计数
引用计数指的是一个数据对象被引用的次数,程序执行的过程中,会更新对象的引用计数,当引用计数更新为0时,就表示这个对象不再有用,可以回收它占用的内存了,所以在引用计数法垃圾识别的任务已经分摊到每一次数据对象的操作中
缺点:
1.高频率的更新引用计数也会造成不小的开销
2.若是A引用了B,B也引用了A,形成循环引用,当A和B的引用计数更新到只剩彼此的相互引用时,引用计数便无法更新到0,也就不能回收对应的内存了
标记——清除算法
程序中用的到的数据一定是从栈、数据段这些根节点追踪得到的数据,虽然能够追踪的到但不代表后续一定会用得到,但是根节点追踪不到的数据就一定不会被用到,也就一定是垃圾。
要识别存活对象,可以把栈、数据段上的数据对象作为root,基于他们进一步追踪,将能追踪到的数据都进行标记,剩下的追踪不到的就是垃圾
算法分两个部分:标记(mark)和清扫(sweep)。标记阶段表明所有的存活单元,清扫阶段将垃圾单元回收。
(1)标记阶段
在此阶段,垃圾回收器会从应用程序的根对象开始遍历。每一个可以从根对象访问到的对象都会被添加一个标识,于是这个对象就被标识为可到达对象。
(2)清理阶段
在此阶段中,垃圾回收器,会对堆内存从头到尾进行线性遍历,如果发现有对象没有被标识为可到达对象,那么就将此对象占用的内存回收,并且将原来标记为可到达对象的标识清除,以便进行下一次垃圾回收操作
优点:无循环引用问题;不用维护计数开销
缺点:需要STW,应用程序的执行会暂停;非渐进式需遍历整个堆空间,开销大
三色标记算法
- 白色:还没有搜索过的对象(标记结束后,白色对象会被当成垃圾对象)
- 灰色:正在搜索的对象
- 黑色:搜索完成的对象(不会当成垃圾对象,不会被GC)
假设现在有白、灰、黑三个集合(表示当前对象的颜色),其遍历访问过程为:
- 初始时,所有对象都在【白色集合】中;
- 将 GC Roots 直接引用到的对象挪到 【灰色集合】中;
- 从灰色集合中获取对象
3.1. 将本对象引用到的其他对象全部挪到 【灰色集合】中;
3.2. 将本对象挪到【黑色集合】里面。 - 重复步骤3,直至【灰色集合】为空时结束。
- 结束后,仍在【白色集合】的对象即为 GC Roots 不可达,可以进行回收。
注:如果标记结束后对象仍为白色,意味着已经“找不到”该对象在哪了,不可能会再被重新引用。
标记——整理算法
标记出所有可达对象,然后将可达对象移动到空间的另外一段,最后清理掉边界以外的内存。
优点:
避免了内存碎片化的问题
适合老年代算法:老年代对象存活率高的情况下,标记整理算法由于不需要复制对象,效率更高
缺点:整理的过程复杂;需要多长遍历内存,导致STW时间比标记清除算法高
分代收集算法
弱分代假说:大部分对象都在年轻时死亡
对于生命周期短的新生代区域,每次回收仅需要考虑如何保留少量存活对象,因此可以采用标记——复制法完成GC
对于生命周期长的老年代区域,可以通过减少gc的频率来提高
效率,同时由于对象存活率高没有额外的空间用于复制,因此一般可以使用标记清除法或标记整理法
这样划分,堆就分成了Young和Old两个分区,因此GC也分为新生代GC和老年代GC
对象的分配策略:
对象优先在新生代上Eden区域分配
大部分对象直接进入老年代
新生代中周期较长的对象在s0或s1区每经过一次新生代Gc,就增加一岁,增加到一定阈值的时候,就进入老年代区域
三、屏障技术
三色标记清晰的描绘了垃圾回收中把存活对象误判为垃圾的情况
1.不出现黑色对象对白色对象的引用(强三色不变式),可以把白色指针着为灰色,也可以把写入的黑色对象退回灰色,这被称为是插入写屏障
2.允许出现黑色对象对白色对象的引用,但是可以保证通过灰色对象可以抵达白色对象(弱三色不变式),提醒我们关注对到白色路径的破坏行为,防止此破坏行为的出现,我们可以把白色对象着色为灰色,这被称为是删除写屏障
实现强/弱三色不变式的通常做法是建立读写屏障
要解决三色标记法的并发性问题,有两种思路:
读屏障技术:非移动式垃圾回收器中,天然的不需要读屏障;在复制式回收器会移动数据避免碎片化,此时读数据也不那么安全,需要读屏障技术,确保用户程序不会访问已经存在副本的陈旧对象
写屏障技术:在写操作中插入指令,目的是把数据对象的修改通知到垃圾回收期,因而写屏障通常都要有一个记录集,记录集采用顺序存储,使用哈希表,记录精确到被修改的对象只记录其所在页
四、运行模式
1.增量式垃圾回收
可以分摊GC时间,避免程序长时间暂停
存在的问题:
1.分摊GC时间,避免程序长时间暂停
2.内存屏障技术,需要额外时间开销,并且由于内存屏障技术的保守性,一些垃圾对象不会被回收,会增加一轮gc的总时长
2.并行垃圾回收
原本需要一个线程全权负责的任务,现在需要分几分交给多个线程
实现较好的负载均衡,会增加线程间的同步开销
3.并发垃圾回收
用户程序与垃圾回收程序并发执行,在多核场景下,就会出现用户程序和垃圾回收程序并行执行的情况
一定程度上利用多核计算机的优势减少了对用户程序的干扰,写屏障的额外开销和保守性问题仍然存在,这是不可避免的
关于gc触发时间:
- 堆内存到达一定阈值
- 距离上次gc超过一定阈值
- 如果当前没有启动gc,则开始新一轮gc
关于gc调优:
- 尽量将小对象组合成大对象
- 尽量使用小数据类型
- 大量string拼接时使用string.join,而不是+号(go中string只读,每一个针对string的操作都会创建一个新的string)
参考
边栏推荐
- 编译error D8021 :无效的数值参数“/Wextra” cl command line error d8021 invalid numeric argument ‘/wextra‘
- FP7195芯片PWM转模拟调光至0.1%低亮度时恒流一致性的控制原理
- 小T成长记-网络篇-1-什么是网络?
- 【我的电赛日记(三)】STM32学习笔记与要点总结
- pytorch模型转libtorch和onnx格式的通用代码
- jest测试,组件测试
- FP5139电池与适配器供电DC-DC隔离升降压电路反激电路电荷泵电路原理图
- 使用npx -p @storybook/cli sb init安装失败,手把手搭建专属的storybook
- 没学好统计学的下场
- Win10电脑需要安装杀毒软件吗?
猜你喜欢
FP7195转模拟调光技术解决智能家居调光频闪和电感噪音的原理
PyTorch③---torchvision中数据集的使用
关于c语言的调试技巧
How to set the win10 taskbar does not merge icons
How to add a one-key shutdown option to the right-click menu in Windows 11
Win11怎么在右键菜单添加一键关机选项
FP7195转模拟恒流调光芯片在机器视觉光源的应用优势
GICv3/v4-软件概述
FP7195降压恒流PWM转模拟调光零压差大功率驱动方案原理图
What is Win10 God Mode for?How to enable God Mode in Windows 10?
随机推荐
【使用Pytorch实现ResNet网络模型:ResNet50、ResNet101和ResNet152】
Win10电脑不能读取U盘怎么办?不识别U盘怎么解决?
KiCad常用快捷键
PyTorch(15)---模型保存和加载
SQL的通用语法和使用说明(图文)
What is Win10 God Mode for?How to enable God Mode in Windows 10?
Binder机制(中篇)
发布模块到npm应该怎么操作?及错误问题解决方案
基于无监督医学图像配准论文(1)
【我的电赛日记(完结)---2021全国大学生电子设计竞赛全国一等奖】A题:信号失真度测量装置
ECP2459耐压60V降压BUCK电路用于WIFI模块供电方案原理图
Please make sure you have the correct access rights and the repository exists. Problem solved
轻量化AlphaPose
LORA芯片ASR6505无线远距离传输8位MCU
2.4G无线小模块CI24R1超低成本
【使用Pytorch实现VGG16网络模型】
DP1101兼容CC1101是SUB1GHz无线收发芯片应用于智能家居
Win11电脑一段时间不操作就断网怎么解决
2020-02-06-快速搭建个人博客
Impressions of Embrace Jetpack