目录
前面的文章(JVM认知的常见10个误区 - kimmking的文章 - 知乎 JVM认知的常见10个误区 - 知乎)里,我们提到了CMS下的这两个参数的关系。其实我们可以全面的看一下Parallel/CMS/G1 GC下的这个关系。
计算公式结论
这里先总结一下,具体的验证过程见下面的步骤:
- 三种GC下,ParallelGCThreads默认值都是CPU线程数(想想为什么?)
- 并行Parallel GC下:ConcGCThreads = 0
- CMS GC下,ConcGCThreads=(ParallelGCThreads+3)/4下取整
- G1 GC下,ConcGCThreads=ParallelGCThreads/4四舍五入
Parallel GC下验证
默认并行Parallel GC下,不存在GC线程和业务线程并发执行的阶段,所以ConcGCThreads无效,为0。
我电脑是8核的,所以ParallelGCThreads为8。
% java -XX:+PrintFlagsFinal -version | grep GCThreads
uintx ConcGCThreads = 0 {product}
uintx ParallelGCThreads = 8 {product}
java version "1.8.0_231"
Java(TM) SE Runtime Environment (build 1.8.0_231-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.231-b11, mixed mode)
CMS GC下验证
CMS GC下默认ParallelGCThreads也为8,ConcGCThreads=(8+3)/4取整=2。
% java -XX:+UseConcMarkSweepGC -XX:+PrintFlagsFinal -version | grep GCThreads
uintx ConcGCThreads = 2 {product}
uintx ParallelGCThreads = 8 {product}
调整一下: CMS基本都是符合公式[C=(P+3)/4下取整]的。
- ParallelGCThreads=1-4, ConcGCThreads显示0; //太小
- ParallelGCThreads=5-8, ConcGCThreads=2; //C=(P+3)/4下取整
- ParallelGCThreads=9-12, ConcGCThreads=3; //C=(P+3)/4下取整
- ParallelGCThreads=13-16, ConcGCThreads=4; //C=(P+3)/4下取整
- ParallelGCThreads取很大,比如P=21或33,都是符合的。
% java -XX:+UseConcMarkSweepGC -XX:ParallelGCThreads=21 -XX:+PrintFlagsFinal -version | grep GCThreads
uintx ConcGCThreads = 6 {product}
uintx ParallelGCThreads := 21 {product}
% java -XX:+UseConcMarkSweepGC -XX:ParallelGCThreads=33 -XX:+PrintFlagsFinal -version | grep GCThreads
uintx ConcGCThreads = 9 {product}
uintx ParallelGCThreads := 33 {product}
G1 GC下验证
最后我们来看一下,把GC换成G1,其他不变,ParallelGCThreads=8,ConcGCThreads=2,这个跟CMS是一样的。
% java -XX:+UseG1GC -XX:+PrintFlagsFinal -version | grep GCThreads
uintx ConcGCThreads := 2 {product}
uintx ParallelGCThreads = 8 {product}
然后我们再来看看其他ParallelGCThreads时候的ConcGCThreads数目,先看一下5和9:
% java -XX:+UseG1GC -XX:ParallelGCThreads=5 -XX:+PrintFlagsFinal -version | grep GCThreads
uintx ConcGCThreads := 1 {product}
uintx ParallelGCThreads := 5 {product}
% java -XX:+UseG1GC -XX:ParallelGCThreads=9 -XX:+PrintFlagsFinal -version | grep GCThreads
uintx ConcGCThreads := 2 {product}
uintx ParallelGCThreads := 9 {product}
这时候就出现一个跟CMS不一样的地方,G1下ConcGCThreads比较小。
CMS: P=5, C=2; P=9, C=3;
G1: P=5, C=1; P=9, C=2;
进一步测试1-12,发现G1下:
- ParallelGCThreads=1, ConcGCThreads=1; //太小
- ParallelGCThreads=2-5, ConcGCThreads=1; //C=P/4四舍五入
- ParallelGCThreads=6-9, ConcGCThreads=2; //C=P/4四舍五入
- ParallelGCThreads=10-13, ConcGCThreads=3; //C=P/4四舍五入
- ParallelGCThreads=14-17, ConcGCThreads=4; //C=P/4四舍五入
可以验证这个公式对于更高数值也成立,例如P=21,33,35, 都是ParallelGCThreads/4四舍五入。
% java -XX:+UseG1GC -XX:ParallelGCThreads=21 -XX:+PrintFlagsFinal -version | grep GCThreads
uintx ConcGCThreads := 5 {product}
uintx ParallelGCThreads := 21 {product}
% java -XX:+UseG1GC -XX:ParallelGCThreads=33 -XX:+PrintFlagsFinal -version | grep GCThreads
uintx ConcGCThreads := 8 {product}
uintx ParallelGCThreads := 33 {product}
% java -XX:+UseG1GC -XX:ParallelGCThreads=35 -XX:+PrintFlagsFinal -version | grep GCThreads
uintx ConcGCThreads := 9 {product}
uintx ParallelGCThreads := 35 {product}