GC优化过程

GC优化的意义

Java程序的垃圾回收由虚拟机自动进行。通常垃圾回收的时间只占程序总运行时间的一小部分,所以通常优化程序优先考虑的并不是GC优化,但是在某些比较特殊的情况下,程序运行的过程中,创建了很多临时变量,短时间内内存占用过高,这时GC对程序的影响便比较明显。而且,了解GC优化还有助于对Java虚拟机内存模型的理解。

GC优化的目标

软件构造课程提出:

A best practice is to tune the time spent doing garbage collection to within 5% of execution time. 最佳做法是将GC时间控制在执行时间 的5%之内。

GC分为Minor GC和Full GC。Minor GC是对年轻代的垃圾回收,它的特点是频率高,速度快;Full GC是对老年代和永久代(JDK8以后变成元数据区)的垃圾回收,它的特点是频率低,速度慢。GC优化的目标是让两者的时间相加最小。

GC优化的方法

  1. Specifying VM heap size  指定虚拟机堆的大小
  2. Choosing a garbage collection scheme 选择合适垃圾回收器
  3. Using verbose garbage collection to determine heap size
  4. Automatically logging low memory conditions
  5. Manually requesting garbage collection
  6. Requesting thread stacks

通常GC优化指的就是分析GC日志并测试找到合适的虚拟机堆设置和指定合适的垃圾回收器。

An acceptable rate for garbage collection is application-specific and should be adjusted after analyzing the actual time and frequency of garbage collections.
If you set a large heap size, full garbage collection is slower, but it occurs less frequently.
If you set your heap size in accordance with your memory needs, full garbage collection is faster, but occurs more frequently.

但是这里存在一个矛盾是:如果使用比较大的堆,Full的频率会减小,但是单次Full GC的时间会增加,总的时间不一定减少。所以GC优化需要不断调整堆的大小,找到最合适的设置。

GC优化过程

测试的程序为一个图应用,读取文本文件中的数据并建图,文件中包含3000个顶点和将近40万条边。在关闭日志的情况下,程序执行时间约为8.8s。

使用Java虚拟机默认设置时,GC的情况如下:可以看到进行了24次Minor GC和2次Full GC,GC的时间占了程序总运行时间将近10%,应当进行适当的优化。

从VisualVM监控结果上可以看到,使用的内存在经过一次比较大的垃圾回收活动后稳定在250m左右,所以从256m开始设置。


  1. -Xms256m -Xmx512m

    使用jstat查看垃圾回收情况:从图上看,Full GC减少了一次,Minor GC出现次数比比默认设置多。由于Minor GC的总时间增加了很多,而Full GC时间并没有减少多少,总的GC时间比默认设置高了14%,说明堆的设置还不够理想。

  1. -Xms512m -Xmx512m

    使用jstat查看垃圾回收情况:从图上看,没有Full GC,Minor GC次数为原来的两倍多,但是每次gc的时间比默认设置的gc时间少了50%~75%。这种情况意味着大部分变量在年轻代就被销毁了,没有转移到老年代。GC时间比上一种设置少了一半,是比较理想的设置。

  1. -Xms512m -Xmx1024m

    使用jstat查看垃圾回收情况:与上一种设置的结果较为相似,没有Full GC,Minor GC次数减少了不少,但是总的时间并没有减少,而且这种设置会使用较多的空间,所以还是第二种设置较为合适。

  1. -Xms512m -Xmx512m -XX:+UseParallelGC

    这一次在第二种设置的基础上增加对垃圾回收器的设置可以看到,垃圾回收的时间进一步降低,说明ParallelGC比默认的垃圾回收器执行速度更快。优化到此,垃圾回收活动的时间已经降低到程序总运行时间的5%以内,基本实现GC优化的目标。

当然这个例子因为避免了Full GC而使程序的GC时间得到优化,在更大型的程序中,Full GC可能是不可避免的,这就要做更多次的测试,在Full GC次数和Full GC时间之间找到一个最优的方案。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章