JVM Garbage Collector——Parallel Collector

内存模型

Java中的内存模型如上图所示,分为两大块old(老年代)和young(新生代),新生代又分为三个区,分别是Eden(伊甸园),from Survivor(幸存者),to Survivor。为什么要这么设计呢,其实和垃圾回收算法有关。

回收算法

标记-清除算法(Mark-Sweep)

标记清除算法将垃圾收集分为两个步骤,第一步是标记,标记的对象也就是即将要回收的垃圾对象。那么如何判定一个对象是垃圾对象呢。一个对象如果不存在任何引用就可以认为它是一个垃圾对象。第二步是清除,将第一步中找出的垃圾对象进行清除。

从上述的描述可知,标记-清除算法容易导致大量的空间碎片,因为回收后的空间是不连续的。

复制算法(Copying)

针对标记清除算法的缺点,有人提出了复制算法。复制算法的核心在于将内存分为两块,在进行对象分配时,只使用其中一块内存(from),当这块内存满了就进行垃圾回收:将存活的对象复制到另一块内存(to)中,此时可以清除from中的所有对象,完成此次垃圾收集。若to满了,便将对象复制到from,清除to中的对象,如此反复。

复制算法保证了空间的连续性,避免出现大量的空间碎片,但是它的空间利用率却不高,相当于只利用了50%的空间。

标记-压缩算法 (Mark-Compact)

在存活对象少,垃圾对象多的情况下,复制算法的效率很高,但是如果存活对象多并且对象较大,此时在使用复制算法,复制成本高,效率很低。

标记-压缩算法可以解决上述的问题,它是基于标记-清除算法进行改进的一种算法。在完成标记之后,标记-压缩算法并不会马上进入清除阶段,而是将存活对象压缩到内存的另一端,之后再将边界外的对象进行清除。

这种方法既避免了碎片的产生,又不需要两块相同的内存空间,因此,其性价比比较高。

并行收集线程数

并行垃圾收集器的垃圾收集线程数与机器的CPU相关。当CPU小于8时,线程数与CPU的数量相等,当CPU大于8时,线程数等于5/8的CPU数

thread = N (N <= 8)
thread = 5/8 * N (N > 8)

可以使用-XX:ParallelGCThreads参数来指定线程数。

设置参数

并行垃圾收集器可以设置的参数有三点

  1. 最大停顿时间
  2. 吞吐量
  3. 堆大小

最大停顿时间

-XX:+MaxGCPauseMills:\ 设置最大垃圾收集停顿时间,单位是毫秒。N是一个大于0的整数,收集器在工作时会调整堆大小或者其他参数,尽可能的把停顿时间控制在N毫秒以内。如果希望减少停顿时间,而把这个值设置的很小,JVM为了实现这个目标,可能会设置一个较小的堆(一个小堆比一个大堆回收的快),而这会导致垃圾收集变得频繁,从而增加了垃圾回收的总时间,降低了吞吐量。

吞吐量

-XX:+GCTimeRatio:\ 设置吞吐量大小。N是一个0-100的整数,收集器将不会花费超过1/(N+1)的时间来用于垃圾收集。例如,假设N=19,那么系统用于收集垃圾的时间将不超过1/(19+1) =5%。默认情况下,N=99,表示不超过1%的时间用于垃圾收集

堆大小

-Xmx表示最大的堆内存,堆的大小也会影响垃圾收集。并行收集器会通过调整堆的大小来实现最大停顿时间以及吞吐量这两个目标。

heap调整

并行收集器会通过调整堆的大小来实现最大停顿时间以及吞吐量这两个目前。收集器通过一定的比例来扩大或缩小堆的大小,默认情况扩大的比例是20%,缩小的比例是5%。这两个比例可以通过参数来调整。

XX:YoungGenerationSizeIncrement=\ 表示的新生代扩大的比例

XX:TenuredGenerationSizeIncrement=\ 表示的老年代扩大的比例

XX:AdaptiveSizeDecrementScaleFactor=\ 用来控制缩小的比例,假设扩大的比例为X,那么缩小的比例就为X/D

OutOfMemoryError

当花费在垃圾收集的时间过多时,收集器将抛出OutOfMemoryError的异常。默认情况下,如果超过98%的时间用于垃圾收集,而回收的堆大小小于2%,那么系统将抛出OutOfMemoryError。

之所以这样设置是为了避免系统花费了大量的时间用于垃圾收集,但是得到的收益却很小。可以用-XX:-UseGCOverheadLimit这个参数来关闭这个特性。

应用场景

停顿时间越短就越适合需要与用户交互的程序,良好的响应速度能提升用户体验,而高吞吐量则可以高效率地利用CPU时间,尽快完成程序的运算任务,主要适合在后台运算而不需要太多交互的任务。

并行收集器可以通过设置参数来设置对应的目标。

参考文献


Previous
JVM Garbage Collector——CMS JVM Garbage Collector——CMS
CMS定义CMS的全称是Concurrent Mark Sweep。 从名称上可以看出CMS的特点,可并发,使用标记-清除算法。CMS是针对老年代垃圾回收的收集器 CMS目标CMS设计时的目标就是获取最小的停顿时间,也就是低延迟。对于响应时
2020-01-04
Next
Prometheus Counter Prometheus Counter
我曾经以为Counter是prometheus中最简单的一种metric,直到我在Grafana中配置counter相关的dashboard之后,才发现自己对于counter的理解有一些偏差。因此这篇博客将会详细的介绍counter的用法。
2019-10-11