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

[每周一更]-(第50期):Go的垃圾回收GC

在这里插入图片描述

参考文章:

  • https://juejin.cn/post/7111515970669117447
  • https://draveness.me/golang/docs/part3-runtime/ch07-memory/golang-garbage-collector/
  • https://colobu.com/2022/07/16/A-Guide-to-the-Go-Garbage-Collector/
  • https://liangyaopei.github.io/2021/01/02/golang-gc-intro/
  • https://xargin.com/impl-of-go-gc/
  • https://www.bookstack.cn/read/qcrao-Go-Questions/spilt.5.GC-GC.md

什么是GC?

Go语言的垃圾回收机制Garbage Collection,简称 GC

在传统编程语言中我们需要关注对象的分配位置,要自己去选择对象分配在堆还是栈上,
但在 Go 这门有 GC 的语言中,集成了逃逸分析功能,帮助我们自动判断对象应该在堆上还是栈上,可以使用 go build -gcflags="-m" 来观察逃逸分析的结果

GC的原理是什么?

Go语言的垃圾回收器采用了并发三色标记清除算法(Concurrent Tri-Color Mark-And-Sweep),(Stop-the-World,简称STW,指的是GC事件发生过程中,会产生应用程序的停顿。)尽可能减少STW(stop the world)时间,
以降低吞吐为代价换取低延迟,实现了高效的垃圾回收。
标记清除算法的基本原理是,垃圾回收器将所有的存活对象标记为“活”的,未被标记的对象则被认为是垃圾。经典的标记清除算法通常分为两个阶段:

  • 标记阶段:垃圾回收器从根对象开始,遍历所有可达对象,并将它们标记为“活”的。
  • 清除阶段:垃圾回收器从堆的起始地址开始遍历,将未被标记的对象清除,回收内存。

Go语言的垃圾回收器采用了三色标记法(Tri-Color Marking),将堆上的内存对象分为三种颜色

  • 白色:未被标记为“活”的对象,是潜在的垃圾,后续可能会被GC回收。
  • 灰色:待扫描的对象,当扫描某个灰色对象时,GC会将其标记为黑色,然后将该对象指向的所有对象都标记为灰色,待后续标记。
  • 黑色:被标记为“活”的对象,在这轮GC中不会被回收。

垃圾回收器开始工作时不存在黑色对象,垃圾回收器会将根对象标记为灰色,并从根对象(通常是栈对象和全局对象)开始遍历。垃圾回收器会将灰色对象标记为黑色,
并将该对象指向的对象标记为灰色。垃圾回收器重复这个过程,直到所有可达对象都被标记为黑色。最后,垃圾回收器清除所有未被标记为黑色的对象,即清除所有白色对象。

GC如何优化?

优化GC的开销是提高系统性能和响应速度的重要手段。

缩短STW时间

Go GC触发时机大体分为三种:

  • 手动触发:调用runtime.GC()
  • 常规触发:Target heap memory = Live heap + (Live heap + GC roots) * GOGC / 100
  • sysmon后台周期性强制触发GC
减少堆内存的分配和释放

GC开销大的根源在于heap object多,Go的每轮GC都是FullGC,每轮都要将所有heap object标记(mark)一遍,
即便大多数heap object都是长期alive的,因此,一个直观的降低GC开销的方法就是减少heap object的数量,即减少alloc。

  • 把小对象聚合到一个结构体中,然后做一次分配即可
  • 内存空间重用,如:sync.Pool

常见的GC

  • 引用计数法
    根据对象自身的引用计数来回收,当引用计数归零时进行回收,但是计数频繁更新会带来更多开销,且无法解决循环引用的问题。
    • 优点:简单直接,回收速度快
    • 缺点:需要额外的空间存放计数,无法处理循环引用的情况;
  • 标记清除法
    标记出所有不需要回收的对象,在标记完成后统一回收掉所有未被标记的对象。
    • 优点:简单直接,速度快,适合可回收对象不多的场景
    • 缺点:会造成不连续的内存空间(内存碎片),导致有大的对象创建的时候,明明内存中总内存是够的,但是空间不是连续的造成对象无法分配;
  • 复制法
    复制法将内存分为大小相同的两块,每次使用其中的一块,当这一块的内存使用完后,将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉
    • 优点:解决了内存碎片的问题,每次清除针对的都是整块内存,但是因为移动对象需要耗费时间,效率低于标记清除法;
    • 缺点:有部分内存总是利用不到,资源浪费,移动存活对象比较耗时,并且如果存活对象较多的时候,需要担保机制确保复制区有足够的空间可完成复制;
  • 标记整理
    标记过程同标记清除法,结束后将存活对象压缩至一端,然后清除边界外的内容
    • 优点:解决了内存碎片的问题,也不像标记复制法那样需要担保机制,存活对象较多的场景也使适用;
    • 缺点:性能低,因为在移动对象的时候不仅需要移动对象还要维护对象的引用地址,可能需要对内存经过几次扫描才能完成;
  • 分代式
    将对象根据存活时间的长短进行分类,存活时间小于某个值的为年轻代,存活时间大于某个值的为老年代,永远不会参与回收的对象为永久代。
    并根据分代假设(如果一个对象存活时间不长则倾向于被回收,如果一个对象已经存活很长时间则倾向于存活更长时间)对对象进行回收。
http://www.lryc.cn/news/273965.html

相关文章:

  • 【嵌入式学习笔记-01】什么是UC,操作系统历史介绍,计算机系统分层,环境变量(PATH),错误
  • 【动态规划】LeetCode-10. 正则表达式匹配
  • lenovo联想拯救者8.8英寸掌上游戏机Legion Go 8APU1(83E1)原装出厂Windows11预装系统
  • 经典目标检测YOLO系列(一)复现YOLOV1(4)VOC2007数据集的读取及预处理
  • Android Studio xml布局代码补全功能失效问题
  • 算法每日一题:队列中可以看到的人数 | 单调栈
  • 报表控件Stimulsoft 2023回顾:都做了哪些产品的改变?
  • Mybatis缓存实现方式
  • C#用StringBuilder高效处理字符串
  • python开发案例教程-清华大学出版社(张基温)答案(4.2)
  • 【MATLAB】【数字信号处理】线性卷积和抽样定理
  • 什么是 MVVM ?
  • Redis(一)
  • 自动驾驶预测-决策-规划-控制学习(1):自动驾驶框架、硬件、软件概述
  • SSM建材商城网站----计算机毕业设计
  • js逆向第9例:猿人学第2题-js混淆-动态cookie1
  • [论文分享]TimesURL:通用时间序列表示学习的自监督对比学习
  • 解决sublime中文符号乱码问题
  • 厚积薄发11年,鸿蒙究竟有多可怕
  • pyDAL一个python的ORM(4) pyDAL查询操作
  • 如何通过Python将各种数据写入到Excel工作表
  • 跟着cherno手搓游戏引擎【2】:日志系统spdlog和premake的使用
  • Ubuntu20.04 上启用 VCAN 用作本地调试
  • LeetCode(31) 下一个排列
  • Git LFS: 简单高效的大文件版本控制
  • 如何培养用户思维
  • 由浅入深理解C#中的事件
  • Nginx(十六) 配置文件详解 - server stream服务流
  • Css中默认与继承
  • gitee上的vue大屏项目