内存管理 gc

Go 语言垃圾收集器的实现原理 | Go 语言设计与实现 (draveness.me)

简单的说,垃圾回收的核心就是标记出哪些内存还在使用中(即被引用到),哪些内存不再使用了(即未被引用),把 未被引用的内存回收掉,以供后续内存分配时使用。

3.3 三色标记法

三色只是为了叙述上方便抽象出来的一种说法,实际上对象并没有颜色之分。这里的三色,

对应了垃圾回收过程中对 象的三种状态

  • 灰色:对象还在标记队列中等待
  • 黑色:对象已被标记,gcmarkBits对应的位为1(该对象不会在本次GC中被清理)
  • 白色:对象未被标记,gcmarkBits对应的位为0(该对象将会在本次GC中被清理)

3.4 Stop The World

 Golang中的STW(Stop The World)就是停掉所有的goroutine,专心做垃圾回收,待垃圾回收结束后再恢复 goroutine。 STW时间的长短直接影响了应用的执行,时间过长对于一些web应用来说是不可接受的,这也是广受诟病的原因之一。 为了缩短STW的时间,Golang不断优化垃圾回收算法,这种情况得到了很大的改善。

屏障技术 #

内存屏障技术是一种屏障指令,它可以让 CPU 或者编译器在执行内存相关操作时遵循特定的约束,目前多数的现代处理器都会乱序执行指令以最大化性能,但是该技术能够保证内存操作的顺序性,在内存屏障前执行的操作一定会先于内存屏障后执行的操作6

想要在并发或者增量的标记算法中保证正确性,我们需要达成以下两种三色不变性(Tri-color invariant)中的一种:

  • 强三色不变性 — 黑色对象不会指向白色对象,只会指向灰色对象或者黑色对象;
  • 弱三色不变性 — 黑色对象指向的白色对象必须包含一条从灰色对象经由多个白色对象的可达路径

4. 垃圾回收优化

4.1 写屏障(Write Barrier)

前面说过STW目的是防止GC扫描时内存变化而停掉goroutine,而写屏障就是让goroutine与GC同时运行的手段。 虽然写屏障不能完全消除STW,但是可以大大减少STW的时间。 写屏障类似一种开关,在GC的特定时机开启,开启后指针传递时会把指针标记,即本轮不回收,下次GC时再确定。 GC过程中新分配的内存会被立即标记,用的并不是写屏障技术,也即GC过程中分配的内存不会在本轮GC中回收。

4.2 辅助GC(Mutator Assist)

为了防止内存分配过快,在GC执行过程中,如果goroutine需要分配内存,那么这个goroutine会参与一部分GC的 工作,即帮助GC做一部分工作,这个机制叫作Mutator Assist。

5. 垃圾回收触发时机

5.1 内存分配量达到阀值触发GC

  每次内存分配时都会检查当前内存分配量是否已达到阀值,如果达到阀值则立即启动GC。

  阀值 = 上次GC内存分配量 * 内存增长率 内存增长率由环境变量 GOGC 控制,默认为100,即每当内存扩大一倍时启动GC。

5.2 定期触发GC

  默认情况下,最长2分钟触发一次GC

5.3 手动触发

  程序代码中也可以使用 runtime.GC() 来手动触发GC。这主要用于GC性能测试和统计。

6. GC性能优化

  GC性能与对象数量负相关,对象越多GC性能越差,对程序影响越大。 所以GC性能优化的思路之一就是减少对象分配个数,比如对象复用或使用大对象组合多个小对象等等。 另外,由于内存逃逸现象,有些隐式的内存分配也会产生,也有可能成为GC的负担。 关于GC性能优化的具体方法,后面单独介绍。

 

 

posted on 2021-09-29 15:53  Ssumer  阅读(109)  评论(0编辑  收藏  举报

导航