March 31, 2019 · Java 本文字数: 1.3k 阅读时长:4 min 全站字数:361.8k

JDK8-GC性能调优指南

  1. Java HotSpot垃圾回收
  2. JDK8默认垃圾回收器
  3. 基于行为的调优
  4. 调优策略

Java HotSpot垃圾回收

垃圾回收器是一种内存管理工具,通过下面的操作来实现自动化内存管理:

  1. 在年轻代分配对象,并将年老的对象晋升到老年代。
  2. 当Java的堆空间占用超过默认阈值,会触发并发标记。通过并发的标记,在老年代中寻找活着的对象。
  3. 通过并行复制来压缩存活对象,从而释放内存空间。

Java HostSpot VM提供多种垃圾回收器,每一种垃圾回收器设计满足不同的应用需求。

JDK8默认垃圾回收器

Serial垃圾回收器适用于大多数小规模的应用,如堆空间小于100M。使用其他的垃圾回收器会有额外的开销或者复杂性,已提供额外的功能特性。Serial不适用于大量内存,多余两个的处理器。对于server模式运行的JVM,会选择并行垃圾回收器作为默认。

对服务器级别的机器的定义:

  1. 2个或者大于两个的物理处理器。
  2. 2G或者大于2G的物理内存。

服务器级别的默认配置:

  1. 高吞吐垃圾回收器
  2. 初始化堆大小是物理内存的1/64,最大1GB
  3. 最大的堆大小是物理内存的1/4,最大是1GB
  4. 使用服务端运行时编译器

64位机器的堆大小和并行垃圾回收器也是不同的。

如果应用可以容忍轻度的频率和时长的停顿, 那么就不需要关心垃圾回收器的选择。但对于有大量数据,多个线程,和高TPS的场景则必须选择合适的垃圾回收器。

Amdahl’s law:并行对问题的加速取决于问题中的有序性部分。大部分的负载是不能并行化的。有些部分是顺序化的,不能通过并行来加速。

JVM提供平台依赖的垃圾回收器、堆大小和运行时编译器配置。从而减少命令行的调优。另外基于行为的调优会动态调整堆大小来满足特定应用的需求。优先使用默认的垃圾回收器。

基于行为的调优

对于并行垃圾回收器,Java SE提供两个调优参数,最大停顿时间和吞吐率。这两个目标可能无法同时满足,堆大小要足够放下所有存活的对象。

  1. 最大停顿时间目标。停顿时间是指垃圾回期间导致应用暂停的时长。垃圾回收器会维护平均的停顿时间及其变化趋势。越近的停顿时间权重越大。可以通过命令行参数 -XX:MaxGCPauseMillis=来调整。垃圾回收器会动态调整堆大小和其他参数来保证最大的停顿时间小于该值。默认是没有设置改值的。这个值的修改会导致垃圾回收更频繁,从而降低总体的吞吐率。垃圾回收器总是优先满足最大停顿时间优于吞吐率。然后,有可能总是无法满足最大停顿时间的要求。
  2. 最大吞吐率目标。吞吐率=(应用时间)/(应用时间+垃圾回收时间)。可以通过命令行参数 -XX:GCTimeRatio=来调整。如果设置该值为19,则最终的值为1/(19+1),即5%的总时间用于垃圾回收。垃圾回收的时间包括年轻代和年老的的总时间。如果无法满足这个值,垃圾回收器会增大年轻代或者年老代的大小,来增加两次垃圾回收时间之间应用的运行时间。
  3. 内存占用。如果最大停顿时间和最大吞吐率都满足了,垃圾回收器会降低堆的大小直到其中一个无法满足。

调优策略

  1. 不要设置最大的堆大小值,除非你需要改成比默认的堆大小还大。
  2. 选择一个合适的应用的吞吐率指标。
  3. 堆大小会根据吞吐率目标的实现与否而改变。应用行为的改变,如较高的对象分配也会导致堆变大以维持相同的吞吐率。
  4. 如果堆已经到了最大值,但是仍然无法满足吞吐率目标, 则需要调整堆的最大值。堆的值要接近最大物理聂村但是要小于导致应用发生内存swap。
  5. 如果还是无法满足吞吐率目标,则在给定的可用内存下,吞吐率目标设置太高了。
  6. 如果吞吐率目标达到,但是停顿时间太长,然后选择一个最大的停顿时间目标,应用需要权衡。
  7. 即使应用稳定运行,堆的空间也会变大。实现吞吐率目标需要增加堆的大小,降低内存占用和停顿时间则需要降低堆大小。