当前位置: 首页 > news >正文

Go内存回收

GC内存回收

go_内存回收_语雀笔记整理

  • GC内存回收
    • GC回收的利弊
    • 常见GC方法
    • 三色标记清扫法
      • 并发后三色标记法会出现的问题
    • 屏障机制解决漏标问题

内容都是学习小徐的公众号以及B站记录的笔记,个人理解,仅供参考

GC回收的利弊

GC指让垃圾回收器以守护者协程的方法在后台运作,按照既定策略自动回收、释放内存。
优势:
最大的好处就是方便开发者,屏蔽了内存回收的细节
另外就是团队开发的时候,由于缺乏全局视野,可能某个临界资源谁都不敢释放,结果就是没有释放,GC拥有全局视野
劣势:
GC提高了下限,但降低了下限。因为开发者失去了控制权,相当于阉割了自由度;
GC需要额外的空间存储状态信息,并且虽然GC大部分时间都可以并发,但还是存在STW,所以GC需要额外成本;

常见GC方法

  1. 标记清扫法

相当于排除法,将存活对象标记,未标记的就是需要清扫的。 问题:清扫后存在内存碎片

  1. 标记压缩

在标记清扫的基础上多了一步压缩,解决了内部碎片的问题。问题:性能上时间复杂度高

  1. 半空间复制(java新生代内存的GC方法)

将空间分外两半,一半fromspace,一半tospace;每次GC时把存活对象迁移到tospace,然后置换fromspace 跟tospace; 问题:空间利用率只有50%,因为右50%一直处于备用状态;(java使用分代内存管理,新生代被认为是GC高频的,采用半空间复制,而老代抗过多轮GC的被认为是低频GC的,低频GC的对象采用标记清扫)

  1. 引用计数

有点类似引用指针或者linux下的node计数器,计数为0的时候说明不被用户关心了,GC时清除计数为0的;问题:可能存在循环引用的问题

三色标记清扫法

属于标记清扫法的一种实现。通过黑、灰、白三种颜色代表对象的状态。 黑色表示对象存活,并且它指向的对象也已经被标记;灰色表示对象存活,但它指向的对象还没有被标记; 白色表示对象还未遍历;

  1. 首先根对象(全局对象、栈上局部变量)标记为黑色,并且根对象的指向对象全部置灰
  2. 将灰色对象所指向的对象全部置灰,然后灰色对象变黑;
  3. 重复以上过程,标记结束后,依然为白色的就是要被清扫的;

Go 1.5之前通过STW暂停全局用户协程,专注完成GC协程工作后再恢复全局用户协程,简单,但是用户会感受到明显的性能割裂感;
image.png
Go1.5之后,Go使用并发三色标记,GC协程跟全局用户协程是并发进行的。但要做到并发,必须解决几个问题。

并发后三色标记法会出现的问题

  1. 漏标问题:(用户让灰色失去白色,黑色得到白色)漏标导致清扫掉了不应该被清扫的对象。GC协程开始GC,灰色B一开始指向白色C,此时用户携程让B删掉C的引用,让A建立对C的引用,然而还在GC的过程中,这就会导致被黑色A引用的白色C颜色不会变灰,那么C就会被清扫。

image.png
漏标问题通过混合写屏障机制解决。

  1. 多标问题:(黑色A已经标记灰色B,用户再黑色A失去灰色B)GC协程下,黑色A引用的对象B先被置灰,然后用户删除A对B的引用,而此时B已经变成了灰色,导致这一轮GCB不会被删除。 多标问题可以接受,因为它只是多抗了一轮GC。

另外goGC的问题:
标记清扫的碎片问题,golang在内存分配的时候使用等级制度,从而将碎片问题局限在内部碎片上。
为何不使用java的分代内存GC:go使用了内存逃逸分析,在编译过程中把生命周期长的放到堆区,短的放到栈区(不通过GC内存回收)

屏障机制解决漏标问题

漏标问题是由于GC协程跟用户协程并发,用户协程操作导致灰色B失去白色C,并且黑色A引用白色C
解决漏标问题的方法论是强弱三色不变式,强三色:禁止黑色引用白色。 弱三色:黑色可以引用白色,前提是灰色不失去白色的引用。

插入屏障(实现强三色不定式)
当黑色对象要引用一个白色对象时,把白色对象置为灰色再引用。

删除屏障(实现弱三色不定式)
当一个白色对象即将被上游删除引用前,会触发屏障将其置灰,之后再删除上游指向其的引用。

混合写屏障
由于栈上的操作频繁,而屏障机制相当于回调函数,所以栈使用屏障机制会造成性能下滑,因此通过混合写屏障机制。GC开始前短暂的STW,将栈上的对象全部置黑(可达对象置灰);GC期间栈上新建的对象默认为黑;堆上正常使用屏障机制。 因此混合写屏障机制大大降低了STW,只有GC开始前有一段STW

相关文章:

  • Python获取QQ音乐歌单歌曲
  • 数据特征采样在 MySQL 同步一致性校验中的实践
  • 计算机未来大方向的选择
  • MViT(ICCV 2021, Meta)论文解读
  • 阶段三:项目开发---大数据系统基础环境准备:任务1:准备系统运行的先决条件
  • vue项目创建+eslint+Prettier+git提交规范(commitizen+hooks+husk)
  • React
  • 开始尝试从0写一个项目--后端(一)
  • 6.8应用进程跨网络通信
  • Airflow: 大数据调度工具详解
  • 0/1背包问题总结
  • 【Python机器学习】处理文本数据——将文本数据表示为词袋
  • 顶级5款有用的免费IntelliJ插件,提升你作为Java开发者的旅程
  • Redis 的过期策略
  • Node.js的下载、安装和配置
  • Apache Pulsar 2.1 重磅发布
  • ComponentOne 2017 V2版本正式发布
  • Laravel深入学习6 - 应用体系结构:解耦事件处理器
  • Linux gpio口使用方法
  • Map集合、散列表、红黑树介绍
  • niucms就是以城市为分割单位,在上面 小区/乡村/同城论坛+58+团购
  • Shell编程
  • 持续集成与持续部署宝典Part 2:创建持续集成流水线
  • 搞机器学习要哪些技能
  • 关于字符编码你应该知道的事情
  • 检测对象或数组
  • 爬虫模拟登陆 SegmentFault
  • 通过git安装npm私有模块
  • No resource identifier found for attribute,RxJava之zip操作符
  • JavaScript 新语法详解:Class 的私有属性与私有方法 ...
  • NLPIR智能语义技术让大数据挖掘更简单
  • #Spring-boot高级
  • #我与Java虚拟机的故事#连载07:我放弃了对JVM的进一步学习
  • #我与Java虚拟机的故事#连载09:面试大厂逃不过的JVM
  • $().each和$.each的区别
  • (html转换)StringEscapeUtils类的转义与反转义方法
  • (剑指Offer)面试题41:和为s的连续正数序列
  • (实战)静默dbca安装创建数据库 --参数说明+举例
  • (算法设计与分析)第一章算法概述-习题
  • (转)MVC3 类型“System.Web.Mvc.ModelClientValidationRule”同时存在
  • (转)树状数组
  • .MSSQLSERVER 导入导出 命令集--堪称经典,值得借鉴!
  • .mysql secret在哪_MYSQL基本操作(上)
  • .NET 漏洞分析 | 某ERP系统存在SQL注入
  • .NET 直连SAP HANA数据库
  • /proc/interrupts 和 /proc/stat 查看中断的情况
  • @DataRedisTest测试redis从未如此丝滑
  • @Validated和@Valid校验参数区别
  • [ IOS ] iOS-控制器View的创建和生命周期
  • [ 数据结构 - C++] AVL树原理及实现
  • [AIGC] Kong:一个强大的 API 网关和服务平台
  • [C#]winform制作仪表盘好用的表盘控件和使用方法
  • [C#]使用PaddleInference图片旋转四种角度检测
  • [C++打怪升级]--学习总目录
  • [HNOI2008]水平可见直线