go的GC原理以及写屏障是什么

Go语言的垃圾回收(GC)原理基于三色标记算法(Tri-color Marking Algorithm)的一个变种——三色标记-清除算法,并且引入了写屏障技术来确保并发标记阶段的正确性。

GC原理概述

  1. 标记阶段

    • Go的垃圾回收器采用并发标记阶段,首先通过根对象(全局变量、栈上的指针等)遍历所有可达的对象,将其标记为黑色。
    • 然后通过工作协程并发地追踪从黑色对象出发的所有可达对象,也将它们标记为黑色。
    • 白色对象表示未被标记且不可达,即为垃圾。
  2. 标记终止阶段

    • 在并发标记结束后,需要进行STW(Stop-The-World)阶段,确保所有正在运行的协程停止,防止在标记结束阶段有新的对象引用关系变更。
  3. 清理阶段

    • 在标记完成后,垃圾回收器会清理(sweep)白色对象,释放它们占用的内存。
  4. 写屏障

    • 写屏障是Go垃圾回收器为了在并发标记阶段维护正确性而引入的一种机制。
    • 写屏障在并发标记期间,每当有协程修改指针引用关系时,会拦截这些写操作,并更新相应的颜色信息,确保并发标记过程中不会漏掉任何新创建或新引用的对象。
    • 在不同版本的Go GC中,写屏障的实现细节有所不同,例如早期的写屏障主要是为了处理栈上的指针,而后来引入了混合写屏障(Hybrid Write Barrier),可以处理堆上的指针,并优化了并发标记和写操作之间的交互。

写屏障的具体作用包括但不限于:

  • 在并发标记期间,当一个指针从黑对象写入白对象时,写屏障会将目标对象的颜色变为灰色,并加入待标记队列,确保后续的标记阶段会正确处理这个对象。
  • 在并发标记后阶段,写屏障还需要处理从任意颜色对象写入灰对象的情况,以维护并发安全。

GMP中, P的数量大小默认是多少? P的数量是固定死的还是可以手动调整的?

在Go语言的GMP(Goroutine-Worker-Mutex)调度模型中,P(Processor)的数量默认情况下并不是固定不变的,而是可以根据需要手动调整。

默认情况下,P的数量在Go程序启动时与机器的处理器核心数相等,即runtime.GOMAXPROCS()的默认值等于系统CPU核心数。这意味着如果你不显式地更改这个值,P的数量会自动适应系统的硬件配置。

但是,你可以通过在代码中调用runtime.GOMAXPROCS(n)函数来手动指定P的最大数量,这里的n是你希望Go运行时能够并行执行Goroutine的最大CPU核心数或者说调度器的数量。这样做允许你根据应用程序的需求和预期负载来调整并发处理能力。

例如,如果你希望限制程序并发执行的Goroutine数量,可以设置一个比系统核心数更小的值;反之,如果希望充分利用多核优势或在特定条件下增加并发,可以设置更大的值。不过需要注意的是,过多的P并不一定能带来性能上的提升,反而可能导致上下文切换的开销增大。

最后编辑: kuteng  文档更新时间: 2024-04-02 09:53   作者:kuteng