【HotSpot虚拟机垃圾回收调优指南】6.并行收集器(Parallel Collector)

并行收集器(Parallel Collector)(这里也称为吞吐量收集器(throughput collector))是与串行收集器(serial collector)类似的分代收集器(generational collector)。串行收集器(serial collector)和并行收集器(Parallel Collector)之间的主要区别是,并行收集器有多个线程,用于加速垃圾收集。

使用命令行-XX:+UseParallelGC启用并行收集器(Parallel Collector)。默认情况下,使用此此命令,minor 和 major收集将并行运行,以进一步减少垃圾收集的开销。

目录

一.并行垃圾收集器的线程数

二.并行收集器"代"的排列

三.并行收集器人体工学(Parallel Collector Ergonomics)

1.指定并行收集器行为

2.并行收集器目标的优先级

3.并行收集器分代大小的调整

4.并行收集器默认堆大小

四.过多的并行收集器时间和OutOfMemoryError

五.并行收集器测量


一.并行垃圾收集器的线程数

在具有<N>硬件线程且<N>大于8的机器上,并行收集器(Parallel Collector)使用<N>的固定比例作为垃圾收集器线程的数量。

对于较大的<N>值,线程的数量约为比值5/8。 当<N>值小于8时,线程的数量可以为<N>。 在选定的平台上,线程的数量下调节到5/16。可以使用命令行参数(稍后将对此进行描述)调整垃圾收集器线程的特定数量。在单处理器的主机上,由于并行执行(例如同步)需要开销,并行收集器的性能可能还不如串行收集器。但是,当运行的应用程序具有中型到大型堆时,在具有两个处理器的计算机上,它通常比串行收集器性能略胜一筹,又当有两个以上的处理器可用时,它比串行收集器性能远远好得多。

可以使用命令行参数-XX:ParallelGCThreads=<N>控制垃圾收集器线程的数量。如果使用命令行参数对堆进行调优,那么使用并行收集器获得良好性能所需的堆大小与使用串行收集器所需的堆大小相同。但是,启用并行收集器应该缩短收集暂停时间。由于多个垃圾收集器线程参与一个minor收集,因此在收集期间,从年轻代升级(老化)到老年代,可能会出现一些碎片minor收集中涉及的每个垃圾收集线程都保留一部分旧的线程用于升级,将可用空间划分为“升级缓冲区(promotion buffers)”可能会导致碎片效应。减少垃圾收集器线程的数量并增加老年代的大小将减少这种碎片效应。

二.并行收集器"代"的排列

在并行收集器中,各"代"的排列是不同的。这种安排如图所示:

Description of Figure 6-1 follows

图片说明:
    该图展示了并行收集器中各代的排列顺序。
    这个图形由一行六个矩形组成。
    这些矩形的标记如下(从左到右):
        1.No label
        2.Virtual
        3.Virtual
        4.Eden
        5.Survivor
        6.Spaces
    矩形1和2被标记为“Old”。矩形3到6被标记为“Young”。矩形7和8被标记为“Perm”。

三.并行收集器人体工学(Parallel Collector Ergonomics)

当使用-XX:+UseParallelGC选择并行收集器时,它启用了一种自动调优方法,支持你指定行为,而不是指定分代的大小和其他低级调优细节信息。

1.指定并行收集器行为

你可以指定最大的垃圾收集暂停时间、吞吐量和占用空间(堆大小)。

1.1.最大垃圾收集暂停时间(Maximum garbage collection pause time):使用命令行参数-XX:MaxGCPauseMillis=<N>指定最大暂停时间目标(The maximum pause time goal )。这被解释为需要<N>毫秒或更少的暂停时间;在默认情况下,没有最大暂停时间目标。如果指定了暂停时间目标,则调整堆大小和其他与垃圾收集相关的参数,以促使垃圾收集暂停时间短于指定的值。然而,期望的暂停时间目标可能并不总是能够实现。这些调整可能会导致垃圾收集器降低应用程序的总体吞吐量。

1.2.吞吐量(Throughput): 吞吐量目标是根据垃圾收集花费的时间垃圾收集之外花费的时间(称为应用程序时间)来衡量的。目标由命令行参数-XX:GCTimeRatio=<N >指定,该参数将垃圾收集时间与应用程序时间的比率设置为1 / (1 + <N >)。例如:利用指令参数 -XX:GCTimeRatio=19 设定垃圾收集总时间的1/20或5%的目标。默认值为99,因此垃圾收集的时间目标为1%。

1.3.内存占用(Footprint):使用选项-Xmx<N>指定最大的堆内存占用。 此外,只要满足其他目标,收集器就有一个隐含的目标,即最小化堆的大小。

2.并行收集器目标的优先级

并行收集器目标是指:最大暂停时间目标(maximum pause-time goal)、吞吐量目标(throughput goal)和最小占用空间目标(minimum footprint goal),目标按此顺序处理:

首先现需要满足最大暂停时间目标(maximum pause-time goal)。只有在满足最大暂停时间目标(maximum pause-time goal)之后,吞吐量目标(throughput goal)目标才会被实现。同样,只有在满足了前两个目标之后,才会考虑最小占用空间目标(minimum footprint goal)。

3.并行收集器分代大小的调整

诸如收集器保持的平均暂停时间之类的统计信息将在每次垃圾收集结束的时候更新。

然后进行测试,以确定目标是否已经达到,并对分代的大小进行任何必要的调整。例外情况是,显式垃圾收集(例如,对System.gc()的调用)在保持统计数据和调整分代大小方面被忽略了。

分代大小的增加和缩小是通过分代大小的固定百分比的增量来完成的,以便分代朝着期望的大小递增或递减。增长和收缩是以不同的速度进行的。默认情况下,分代以20%的增量增长,以5%的增量收缩。增长百分比由年轻代的命令行参数-XX:YoungGenerationSizeIncrement = <Y>和老年代的-XX:TenuredGenerationSizeIncrement = <T>控制。 通过命令行参数-XX:AdaptiveSizeDecrementScaleFactor = <D>可以调整生成收缩的百分比。 如果增长增量为X%,则收缩的减少量为X / D%。

如果收集器决定在启动时增长分代,则会在增量中添加一个补充百分比。这个增量随着收集次数的增加而减少,没有长期效果。该补充的目的是提高启动性能。收缩的百分比没有补充。

如果未满足最大暂停时间目标,则一次只缩小一个分代的大小。 如果两代的暂停时间都高于目标,那么具有较大暂停时间的分代的大小先缩小。

如果吞吐量目标没有得到满足,那么这两代的大小都会增加。每一个都按其对总垃圾收集时间的贡献的比例增加。例如,如果年轻代的垃圾收集时间占总收集时间的25%,如果年轻代的完全增量为20%,那么年轻代大小将增加5%。

4.并行收集器默认堆大小

除非在命令行中指定了初始和最大堆大小,否则它们将根据计算机上的内存量进行计算。 默认的最大堆大小是物理内存的四分之一,而初始堆大小是物理内存的1/64。 分配给年轻代的最大空间是总堆大小的三分之一。

并行收集器初始和最大堆大小的规范:

你可以使用选项-Xms(初始堆大小)和-Xmx(最大堆大小)指定初始堆大小和最大堆大小

如果你知道应用程序需要多少堆才能正常工作,那么可以将-Xms和-Xmx设置为相同的值。如果你不知道,那么JVM将从使用初始堆大小开始,然后增长Java堆,直到找到堆使用和性能之间的平衡。

其他参数和选项可以影响这些默认值。要验证默认值,使用-XX:+PrintFlagsFinal选项,并在输出中查找-XX:MaxHeapSize。例如,在Linux或Solaris上,可以运行以下命令:

java -XX:+PrintFlagsFinal <GC options> -version | grep MaxHeapSize

四.过多的并行收集器时间和OutOfMemoryError

如果在垃圾收集(GC)中花费了太多时间,并行收集器将抛出OutOfMemoryError错误。

如果超过98%的总时间花在垃圾收集上,而回收的堆不足2%,则抛出OutOfMemoryError。该特性旨在防止应用程序长时间运行,同时由于堆太小而进展很少或没有进展。如有必要,可以通过向命令行添加-XX:-UseGCOverheadLimit来禁用此功能

五.并行收集器测量

并行收集器输出的垃圾收集详细与串行收集器输出的垃圾收集详细在本质上是相同的。

猜你喜欢

转载自blog.csdn.net/weixin_37519752/article/details/89449779