尽管Go
1.5刚刚发布,仍然相对较新,但是Go团队已经在致力于改进其新的低延迟并发垃圾收集器,希望Go更适合新的应用领域。Google工程师Austin
Clements和Rick
Hudson如是说。

澳门新葡亰,1、serial收集器

serial是一个单线程的垃圾收集器,它只会使用一个cpu、一个收集线程工作;它在进行gc的时候,必须暂停其他所有线程到它工作结束(这种暂停往往让人难以接受)。

对于单个cpu的情况下,serial是没有线程交互的开销,效率要好于其他。例如在一个简单的桌面应用,只有几十M的内存,他的停顿时间可能只有几十毫秒,所以一般默认的client模式下都是用的serial做默认垃圾收集器。

serial收集器

Go 1.5用新的垃圾收集器代替了原来的STW(stop-the-world)
GC,解决了延迟问题。当负载较重时,每50ms,新的GC的活动时间可以控制在10ms以下,从而使Go程序在一般情况下能运行得更快些。在更极端的情况下,停顿可以从300ms降到4ms。

2、parnew收集器

parnew其实就是serial的多线程版本,parnew在单线程的情况下甚至不如serialparnew是除了serial之外唯一能和CMS配合的。

parnew默认开启收集线程数和cpu的数量相同,我们可以利用-XX:ParallelGCThreads参数来控制它开启的收集线程数。

parnew收集器

Go
1.6的目标是进一步稳定GC,并在以下几个方面做出改进:

3、parallel scavenge收集器

parallel scavenge主要就是关注吞吐量。
所谓吞吐量:运行用户代码的世界/(运行用户代码时间+GC花费的时间)。
parallel scavenge收集器中,提供了2个参数来控制吞吐量:

  • -XX:GCTimeRatio:gc时间占用的总比例,也就是吞吐量的倒数。
  • -XX:MaxGCPauseMillis:最大的暂停毫秒数(这个数值并非越小越好,如果把他设置小了,系统会根据这个值调整空间的大小,也就会加快GC的频率)

parallel scavenge可以设置开启-XX:UseAdaptiveSizePolicy,开启这个参数之后就无需关注新生代大小eden和survivor等比例,晋升老年代对象年龄的这些细节了。

parallel scavenge的工作细节

  • 状态协调(State coordination):Go 1.5
    GC有个主要瓶颈是从Go
    1.4继承来的,源自其集中式的GC协调器(coordinator),这是一个单独的goroutine,它会将工作进一步分派给worker
    goroutine去完成。一种解决方案是用去中心化的状态机代替集中式协调器。这样修改有个额外的好处,使得重新设计标记完成屏障(mark completion
    barrier)成为可能,因为它已经变得非常凌乱,而且性能很差。

  • 信用系统(Credit system):Go
    1.5在两个不同的地方使用了一个信用系统:一个是确保清扫(sweeping)在一个GC周期和下一次触发堆操作(the
    next heap
    trigger)之间完成,一个是确保扫描(scanning)在触发堆操作(an heap trigger)和随后实现堆处理目标之间完成。改进信用系统的一种建议方法是,使其操作总是在black阶段进行,以避免未完成的分配操作进入下一个GC周期。

  • 标记结束(Mark
    termination):
    根据Clements和Hudson的介绍,在Go
    1.5中,标记结束阶段是停顿时间的大头。这里的目标是尝试并确保大部分应用可以在10ms停顿的阈值下运行,这也是Go
    1.5在很多情况下已经实现了的。希望所做修改的复杂度较低或中等,比如把finalizer扫描从标记结束阶段移到并发扫描,这样对于每1GB大小的堆,应该可以节省1ms,以及去掉一个成本很高的计数循环,对于较大的堆,这个循环占去了标记阶段的另外一半。

  • sweeper和scavenger:某些程序会在sweeper上消耗大量时间,在这上面投入些精力,应该有性能改进。一个非常激进的方案是完全去掉sweeper。还有一个不那么激进的方案,可以在GC阶段最后,尽早释放较大的对象,并且在所有的系统上支持scavenger,不管物理页面是多大。

4、serial old收集器

serial收集器的老年代版本,使用标记整理算法,主要有两个作用:

  • jdk5之前和parallel scavenge配合使用
  • 作为cms失败的后备收集方案
网站地图xml地图