谨慎乐观。首先这不是一个全新GC, 而是原有GC上加的一个新优化路径。TOC要解决的问题或者背景假设是很经典的,用正常人的话来说就是:「程序执行中产生的大部分对象的生命周期都很短,而且都只在局部使用。」基于局部使用假设,首先可以做的是静态的逃逸分析,在编译期就指出很大一部分对象的生命周期,这个 Go 也已经做了,而且还在优化。至于不能在编译期确定生命周期的,在运行时的垃圾回收中很常见的做法就是分代 GC, 让年轻对象更快更容易回收,降低全局 GC 压力。
而 TOC 基于的假设是上面短生命周期假设的一个特化版本:
那么,如果可以准确标记哪些对象是跨 goroutine 共享了,那在goroutine结束的时候把没有共享出去的全回收掉就可以了。实现一个准确及时回收内存还能用好多核还性能好的分代GC非常复杂,还要针对各种场景优化,我记得 golang-dev 邮件组讨论过要不要实现分代 GC, 不过看来结论是 TOC 了,TOC其实就是一个基于特化假设的特化简单实现,这很 gopher.
一个对象有没有跨goroutine共享出去(文档里的publish)是有传递关系的,你被一个published的对象引用了那你和所有你引用的对象也published了,如果我没看错,现在的设计是要在write barrier上递归标记这个状态的。我会担心这样下来是否会有一些场景的运行时开销比原来更大了。TOC 对它要优化的场景应该是能同时实现提高吞吐(降低运行时开销),降低停顿时间和节省内存占用的目标的,还能在多核环境高效扩展,而这个场景也确实是网络服务中的统治性场景。但还是要看有没有被严重劣化的场景,以及最后真实服务的综合效能。
这种运行时优化的东西,现在已经很难有一个超级聪明的想法然后秒杀所有前人成果了,都是针对实用场景优化,很多时候只要运行时数据摆在你面前,解决方法是显而易见的。我一直对 Go 的运行时优化持乐观态度,并不是因为有大牛操刀,而是因为他们可以从Google内部机群拿到巨量的运行时数据来支持设计决策和测试新想法。保持简单,看实际环境数据做优化,这个大方向是靠谱的。