原文:Java Platform, Standard Edition HotSpot Virtual Machine Garbage Collection Tuning Guide--The Parallel Collector。
并行收集器(也称为吞吐量收集器),与串行收集器类似都是分代收集器;主要的区别是使用多个线程来加速垃圾回收。
使用命令行选项'-XX:+UseParallelGC'启用并行收集器。默认情况下,使用此选项,'minor collection'和'major collection'都会并行执行,以进一步减少垃圾收集开销。
在拥有N(N>8)个硬件线程的机器上,并行收集器使用固定比例的N值作为垃圾收集器线程的数量。对于N值较大的情况,比例约为5/8。当N值低于8时,使用的数值为N。在选定的平台上,比例下降为5/16。可以使用命令行选项(稍后将对此进行描述)调整垃圾收集线程的特定数量。在只有一个处理器的主机上,由于并行执行(例如同步,线程间通信)所需的开销,并行收集器的性能可能不如串行收集器。但是,当运行具有中型到大型堆的应用程序时,在具有两个处理器的机器上,它的性能通常要比串行收集器好一些,而且当有两个以上可用处理器时,它的性能通常要比串行收集器更好。
可以使用命令行选项'-XX:ParallelGCThreads=
Generations
正如前面提到的,在并行收集器中,代的排列是不同的(相比于串行收集器)。这种排列如图6-1所示:
Parallel Collector Ergonomics
在服务器类机器上,默认情况下选择并行收集器。此外,并行收集器使用一种自动调优方法,允许您指定特定的行为,而不是代的大小和其他更低层级的调优细节。您可以指定最大GC停顿时间、吞吐量和占用空间(堆大小)。
Priority of Goals
这些目标的处理顺序如下:
首先满足最大GC停顿时间目标。只有在达到这个目标之后,才会处理吞吐量目标。同样,只有在满足了前两个目标之后,才会考虑(内存)空间占用目标。
Generation Size Adjustments
收集器保存的平均GC停顿时间等统计信息会在每次收集结束时更新。然后进行测试,以确定目标是否已达到,并对代的大小进行任何必要的调整。例外情况是,显式地GC(例如,对System.gc()的调用)会忽略保存统计信息和调整代的大小。
代的大小的增长和收缩是通过一个固定百分比(相对于代大小的百分比)来完成的,这样代就可以逐步的增加或减小,直到它的预期大小。增长和收缩的比率不同。默认情况下,代以20%的增量增长,以5%的增量收缩。年轻代增长的百分比由命令行选项'-XX:YoungGenerationSizeIncrement=
如果收集器决定在启动时增加代(的内存大小),则在增量中添加一个补充百分比。这种补充随着收集次数的增加而减少,没有长期效果。该补充的目的是提高启动时性能。缩减的百分比没有补充。
如果没有达到最大GC停顿时间目标,则每次只收缩一个代的大小。如果两代的暂停时间都超过了目标,则首先收缩暂停时间较大的代的大小。
如果吞吐量目标没有得到满足,那么这两代的大小都会增加。每一个都按其对总垃圾收集时间的贡献的比例增加。
例如,如果年轻代的垃圾收集时间占总收集时间的25%(四分之一),如果年轻代的完全增量为20%,那么年轻代将增加5%(20%*25%)。
Default Heap Size
除非在命令行上指定了初始堆大小和最大堆大小,否则将根据计算机上的内存大小计算它们。
Client JVM Default Initial and Maximum Heap Sizes
默认的最大堆大小是物理内存大小(192 MB以下)的一半,否则是物理内存大小(1gb以下)的四分之一。
例如,如果您的计算机有128 MB的物理内存,那么最大堆大小为64 MB,如果大于或等于1 GB的物理内存,则最大堆大小为256 MB。
JVM实际上不会使用最大堆大小,除非您的程序创建了足够多的对象来需要它。在JVM初始化期间分配的数量要少得多,称为初始堆大小。这个数量至少是8mb,否则是物理内存的1/64(1GB以下)。
分配给年轻代的最大空间量是总堆大小的三分之一。
Server JVM Default Initial and Maximum Heap Sizes
默认的初始堆大小和最大堆大小在服务器JVM上的工作方式类似于在客户机JVM上的工作方式,只是默认值可以更高。在32位jvm上,如果有4 GB或更多的物理内存,默认的最大堆大小可以达到1 GB。在64位jvm上,如果有128 GB或更多的物理内存,默认的最大堆大小可以达到32 GB。您总是可以通过直接指定这些值来设置更高或更低的初始堆和最大堆。
Specifying Initial and Maximum Heap Sizes
可以使用命令行'-Xms'(初始堆值)和'-Xmx'(最大堆值)指定初始堆大小和最大堆大小。如果知道应用程序需要多少堆才能正常工作更好,可以将'-Xms'和'-Xmx'设置为相同的值。如果没有,JVM将从使用初始堆大小开始,然后增长Java堆,直到找到堆使用和性能之间的平衡。
其他参数和选项可以影响这些默认值。要验证默认值,请使用'-XX:+PrintFlagsFinal'选项并在输出中查找'MaxHeapSize'。例如,在Linux或Solaris上,可以运行以下命令:“java -XX:+PrintFlagsFinal
Excessive GC Time and OutOfMemoryError
如果在垃圾收集中花费了太多的时间,并行收集器将抛出OutOfMemoryError:如果超过98%的总时间花费在垃圾收集中,并且回收的堆不足2%,那么将抛出OutOfMemoryError。该特性旨在防止应用程序长时间运行,同时由于堆太小而很少或没有进展。如果需要,可以通过在命令行中添加选项'-XX:-UseGCOverheadLimit'禁用此功能。
Measurements
并行收集器的详细垃圾收集器输出与串行收集器的输出本质上是相同的。