Yra's blog Yra's blog
Homepage
  • LeetCode周赛
  • Acwing周赛
  • 刷题整理
  • 题解
  • CPP
  • Golang
  • System

    • MIT6.S081 Labs
  • Computer Networking

    • CS144: Computer Networking
  • DataBase

    • MySQL
    • Redis
  • Others

    • ......
  • Paper Reading

    • Petri Net
  • Static Analysis

    • NJU Course Notes
  • Deep Learning

    • Dive into Deep Learning
Casual Records
Archives

Yra

Only a vegetable dog.
Homepage
  • LeetCode周赛
  • Acwing周赛
  • 刷题整理
  • 题解
  • CPP
  • Golang
  • System

    • MIT6.S081 Labs
  • Computer Networking

    • CS144: Computer Networking
  • DataBase

    • MySQL
    • Redis
  • Others

    • ......
  • Paper Reading

    • Petri Net
  • Static Analysis

    • NJU Course Notes
  • Deep Learning

    • Dive into Deep Learning
Casual Records
Archives
  • CPP

  • Golang

    • Go 语言中的 GC 问题整理
      • Go 语言中的 Channel 相关问题整理
    • Programming Languages
    • Golang
    Yra
    2023-09-06
    目录

    Go 语言中的 GC 问题整理

    # GC

    • GC 清理堆数据,分为手动垃圾回收 和 自动垃圾回收

    • 理论基础:可达性 等价于 存活性

    • 追踪式垃圾回收

      • 三色标记–清扫算法 -> 内存碎片化 -> 三色标记-整理算法(标记完后移动非垃圾数据,使内存更紧凑)

      • 复制式回收算法:将堆内存分为 To 区域和 From 区域,GC 时扫描 From,把有效数据复制到 To 中,最后交换 From 区域和 To 区域

        • 堆内存里利用率低,一般搭配其他垃圾回收算法使用
      • 分代回收:基于弱分代假说:大部分对象都在年轻时死亡

        • 将经受住特定次数的对象成为老年代对象,其余为新生代对象,新生代对象成为垃圾的概率高于老年代对象

        • 可以降低对老年代对象进行垃圾回收的概率,或者对不同对象采取不同垃圾回收算法,例如 复制时回收算法

    • 引用计数垃圾回收

      • 为每个对象维护一个引用计数,当引用计数为 0 时回收该数据,类似 C++ 中的智能指针

        • 高频率更新计数会带来不小的开销

        • 循环引用问题,C++ weak_ptr 解决(其不控制对象生命周期,不增加引用计数)

    • 用户进程暂停去专注进行垃圾回收,称为 STW(Stop The World)

      • 用户进程与 GC 交替执行,称为增量式垃圾回收;但交替执行中用进程可能会修改某些对象,导致 gc 的误判
    • 三色抽象中,黑色对象表示已经处理完,灰色对象还会被继续处理,当全是黑色数据后剩余的白色对象就是垃圾。

      • 对于误判垃圾的情况:黑色对象到白色对象有引用,但没有灰色对象到白色对象的引用,白色对象会被误判为垃圾

        • 强三色不变式:没有从黑色对象直接到白色对象的引用。确保了一旦对象变为黑色,则一定可达,且其引用的所有对象也可达

        • 弱三色不变式:允许黑色对象直接到白色对象的引用,但要保证可以通过灰色对象到达白色对象

      • 通过建立 “读 / 写屏障” 实现 强弱三色不变式

        • 写屏障会在写操作中插入指令,目的是把数据对象的修改通知到垃圾回收器,所以通常会有个记录集

          • 强三色不变式中称为插入写屏障:当一个黑色对象被修改引用到一个白色对象,则将白色对象修改为灰色,或者把黑色对象退为灰色

          • 弱三色不变式中称为删除写屏障:当删除灰色对象到白色对象的引用时,将白色对象修改为灰色

        • 读屏障,非移动式垃圾回收器天然不需要读屏障;类似复制式回收器的移动式垃圾回收期则需要读屏障来保证安全

          • 确保用户程序不会访问到已经存在副本的陈旧对象

            • eg.在复制式回收器中,第一段 STW 中,A 从 From 被拷贝到了 To;接着交替执行的用户程序中,B 引用了 A;第二段 STW 中,B 被拷贝到了 To,此时 To 中的 B 还持有着 From 中 A 的陈旧对象。当 From 被清楚后,再通过 B 访问 A 就会出现错误。
    • 多核场景下,分为并行垃圾回收(只有垃圾回收程序执行)和 并发垃圾回收(垃圾回收程序会和用户程序并发执行)

      • 并行垃圾回收会有分工不均引发的负载均衡问题、同步问题、重复处理数据问题(From 到 To 的重复复制)

      • 并发垃圾回收会有锁竞争的问题,比如用户程序和垃圾回收程序会竞争写屏障的记录集。同时因为有多个线程,为了避免同步开启写屏障的延迟,所以一般采用主体并发垃圾回收,在此基础上支持增量式,便是主体并发增量式回收。

    # Go 语言的 GC 的简单描述

    • Go 语言的 GC 采用 标记-清扫算法,支持主体并发增量式回收,使用插入和删除两种写屏障结合的混合写屏障

    • 标记准备阶段(Mark Setup)

      1. STW 暂停程序执行

      2. 启动标记工作协程

      3. 启动写屏障

      4. 找到 roots 放到标记队列中

      5. 取消程序暂停

    • 标记阶段(Marking) 和用户进程并发执行

      1. 从标记队列中取出对象,标记为黑色

      2. 追踪对象,将后面的对象放进标记队列中,标记为灰色

      3. 重复 1、2,知道队列为空

      4. 扫描过程中,如果用户进程创建或者修改了对象会触发写屏障,将对象放入单独的 marking 队列,标记为灰色

    • 标记终止阶段(Mark Termination)

      1. STW 暂停程序执行

      2. rescan:将 Marking 阶段中触发写屏障产生的队列中对象取出,标记为黑色,并检测是否有指向另一个对象;若有则放入标记队列

      3. 关闭写屏障

      4. 取消程序暂停

    • 清理阶段(Sweeping)

      1. 清除所有被标记为白色的对象,内存管理结构中有个 bitmap 区域可以进行标记是否为黑色
    • GC 触发时机

      1. 主动触发:调用 runtime.GC() 方法

      2. 被动触发:

        • 定时触发:由 runtime.forcegcperiod 变量控制,默认为 2 分钟。当超过 2 分钟没有 gc,则触发 gc

        • 根据内存分配阈值触发:由环境变量 GOGC 控制,默认为 100。如果当前堆内存是上次 GC 结束后占用内存的 2 倍时,则触发 gc

    #Programming Languages#Golang
    Last Updated: 9/6/2023, 3:40:10 PM
    右值引用与std::move()
    Go 语言中的 Channel 相关问题整理

    ← 右值引用与std::move() Go 语言中的 Channel 相关问题整理→

    最近更新
    01
    408 计组笔记
    07-19
    02
    Dive into Deep Learning
    01-27
    03
    25 考研随记
    11-27
    更多文章>
    Theme by Vdoing | Copyright © 2022-2025
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式