垃圾回收器背后的更多操作
这一小节会深入探索go垃圾回收器。
go垃圾回收器的主要关注点是低延迟,也就是说为了进行实时操作它会有短暂的暂停。另一方面,创建新对象然后使用指针操作存活对象是程序始终在做的事情,这个过程可能最终会创建出不会再被访问到的对象,因为没有指向那些对象的指针。这种对象即为垃圾对象,它们等待被垃圾回收器清理然后释放它们的空间。之后它们释放的空间可以再次被使用。
垃圾回收中使用的最简单的算法就是经典的标记清除算法(mark-and-sweep):算法为了遍历和标记堆中所有可触达对象,会把程序停下来(stop the world)。之后,它会去清扫(sweeps)不可触达的对象。在算法的标记(mark)阶段,每个对象被标记为白色、灰色或黑色。灰色的子对象标记为灰色,而原始的对象此时会标记为黑色。没有更多灰色对象去检查的话就会开始清扫阶段。这个技术适用是因为没有从黑色指向白色的指针,这是算法的基本不变要素。
尽管标记清除算法很简单,但是它会暂停程序的运行,这意味着实际过程中它会增加延迟。go会通过把垃圾回收器作为一个并发的处理过程,同时使用前一节讲的三色算法,来降低这种延迟。但是,在垃圾回收器并发运行时候,其它的过程可能会移动指针或者创建对象,这会让垃圾回收器处理非常困难。所以,让三色算法并发运行的关键点就是,维持标记清除算法的不变要素即没有黑色的对象能够指向白色集合对象。
因此,新对象必须进入到灰色集合,因为这种方式下标记清除的不变要素不会被改变。另外,当程序的一个指针移动,要把指针所指的对象标记为灰色。你可以说灰色集合是白色集合和黑色集合中间的“屏障”。最后,每次一个指针移动,会自动执行一些代码,也就是我们之前提到的写屏障,它会去进行重新标色。
为了能够并发运行垃圾回收器,写屏障代码产生的延迟是必要的代价。
注意Java程序语言有许多垃圾回收器,它们在各种参数下能够进行高度配置。其中一种垃圾回收器叫G1,推荐在低延迟应用的程序使用它。
一定要记住,Go垃圾回收器是一个实时的垃圾回收器 ,它是和其他goroutines一起并发运行的
在第11章,代码测试,优化以及分析,你会学习到如何能够用图表的方式呈现程序的性能。这一章节也会包括一些关于Go垃圾回收器操作的一些信息。
下一节会介绍**不安全代码(unsafe code)和unsafe
的go标准库