简介

咱们常常会听到甚至须要本人入手去做GC调优。那么GC调优的目标到底是什么呢?让程序跑得更快?让GC耗费更少的资源?还是让程序更加稳固?

带着这些疑难来读一下这篇文章,将会失去一个零碎的甚至是不一样的后果。

那些GC的默认值

其实GC或者说JVM的参数十分十分的多,有管制内存应用的:

有管制JIT的:

有管制分代比例的,也有管制GC并发的:

当然,大部分的参数其实并不需要咱们自行去调整,JVM会很好的动静帮咱们设置这些变量的值。

如果咱们不去设置这些值,那么对GC性能比拟有影响的参数和他们的默认值有哪些呢?

GC的抉择

咱们晓得JVM中的GC有很多种,不同的GC抉择对java程序的性能影响还是比拟大的。

在JDK9之后,G1曾经是默认的垃圾回收器了。

咱们看一下G1的调优参数。

G1是基于分代技术的,其实JVM还在开发一些不再基于分代技术的GC算法,比方ZGC,咱们能够依据须要来抉择适宜咱们的GC算法。

GC的最大线程个数

GC是由专门的GC线程来执行的,并不是说GC线程越多越好,这个默认线程的最大值是由heap size和可用的CPU资源动静决定的。

当然你能够应用上面两个选项来批改GC的线程:

 -XX:ParallelGCThreads=threads 设置STW的垃圾收集线程数 -XX:ConcGCThreads = n 设置并行标记线程的数量

个别状况下ConcGCThreads能够设置为ParallelGCThreads的1/4。

初始化heap size

默认状况下加初始化的heap size是物理内存的1/64。

你能够应用

 -XX:InitialHeapSize=size

来从新设置。

最大的heap size

默认状况下最大的heap size是物理内存的1/4。

你能够应用:

 -XX:MaxHeapSize

来从新设置。

分层编译技术

默认状况下分层编译技术是开启的。你能够应用:

 -XX:-TieredCompilation

来敞开分层编译。如果启用了分层编译,那么可能须要关注JIT中的C1和C2编译器带来的影响。

咱们到底要什么

鱼,我所欲也,熊掌亦我所欲也;二者不可得兼,舍鱼而取熊掌者也。--孟子

java程序在运行过程中,会产生很屡次GC,那么咱们其实是有两种统计口径:

  1. 均匀每次GC执行导致程序暂停的工夫(Maximum Pause-Time Goal)。
  2. 总的破费在GC上的工夫和利用执行工夫的比例(Throughput Goal)。

最大暂停工夫

单次GC的暂停工夫是一个统计平均值,因为单次GC的工夫其实是不可控的,然而取了平均值,GC就能够动静去调整heap的大小,或者其余的一些GC参数,从而保障每次GC的工夫不会超过这个平均值。

咱们能够通过设置:

-XX:MaxGCPauseMillis=<nnn>

来管制这个值。

不管怎么设置这个参数,总体须要被GC的对象必定是固定的,如果单次GC暂停工夫比拟短,可能会须要缩小heap size的大小,那么回收的对象也比拟少。这样就会导致GC的频率减少。从而导致GC的总工夫减少,影响程序的Throughput。

吞吐率

吞吐率是由破费在GC上的工夫和应用程序上的工夫比率来决定的。

咱们能够通过设置:

-XX:GCTimeRatio=nnn

来管制。

如果没有达到throughput的指标,那么GC可能会去减少heap size,从而缩小GC的执行频率。然而这样会减少单次的Maximum Pause-Time。

如果throughput和maximum pause-time的参数同时都设置的话,JVM会去尝试去动静缩小heap size的大小,直到其中的一个指标不能满足为止。

相对而言,G1更加偏重于最大暂停工夫,而ZGC更加偏重于吞吐率。

本文作者:flydean程序那些事

本文链接:http://www.flydean.com/jvm-diagnostic-gc/

本文起源:flydean的博客

欢送关注我的公众号:程序那些事,更多精彩等着您!