我有一些短期应用程序,通常(但不总是)不需要任何GC(适合在堆中,通过未引起OOM的epsilon GC证明)。
有趣的是,即使仍有大量的堆可用,G1仍然会很早地启动:
[0.868s][info ][gc,start ] GC(0) Pause Young (Normal) (G1 Evacuation Pause)
[0.869s][info ][gc,task ] GC(0) Using 13 workers of 13 for evacuation
[0.872s][info ][gc,phases ] GC(0) Pre Evacuate Collection Set: 0.0ms
[0.873s][info ][gc,phases ] GC(0) Evacuate Collection Set: 2.8ms
[0.873s][info ][gc,phases ] GC(0) Post Evacuate Collection Set: 0.4ms
[0.873s][info ][gc,phases ] GC(0) Other: 1.0ms
[0.873s][info ][gc,heap ] GC(0) Eden regions: 51->0(45)
[0.873s][info ][gc,heap ] GC(0) Survivor regions: 0->7(7)
[0.873s][info ][gc,heap ] GC(0) Old regions: 0->2
[0.873s][info ][gc,heap ] GC(0) Humongous regions: 4->2
[0.873s][info ][gc,metaspace ] GC(0) Metaspace: 15608K->15608K(1062912K)
[0.874s][info ][gc ] GC(0) Pause Young (Normal) (G1 Evacuation Pause) 55M->10M(1024M) 5.582ms
[0.874s][info ][gc,cpu ] GC(0) User=0.00s Sys=0.00s Real=0.01s
[...]
让我想知道为什么垃圾回收器在这里运行,因为堆只有55MB。
总体上,我通常会有10-15次GC运行,这些运行会聚集到消耗用户CPU时间约1秒的程度,我希望避免这种情况。
JVM: openjdk version "11.0.16" 2022-07-19
JVM ARGS: -Xms1g -Xmx2g -XX:+PrintGCDetails -Xlog:gc+cpu=info -Xlog:gc+heap+exit
问题:
我如何调整 G1(jdk 11)的设置,让它尽可能晚地启动(例如在堆/伊甸园填满了90%时),以理想情况下避免任何GC暂停/运行?
增加-XX:InitiatingHeapOccupancyPercent
(例如到90%)在我的情况下没有帮助。
编辑:
通过在您的JVM上执行此Java类来自己尝试:
public class GCTest {
public static void main(String[] args) {
java.util.Map<String,byte[]> map = new java.util.HashMap<>();
for(int i=0;i<1_000_000;i++)
map.put(i+"", new byte[i % 256]);
System.out.println(map.size());
}
}
该应用程序使用约260MB堆并运行不到500ms。
当使用以下jvm参数启动时:
-Xms1g -Xmx2g -XX:+PrintGCDetails -Xlog:gc + cpu = info -Xlog:gc + heap + exit
您将得到约5-6次GC运行(在java 11 + 16热点vm中测试)。
GC Epsilon测试清楚地表明它可以在不进行任何GC的情况下运行。
挑战:
您能否找到强制G1在此处不进行任何GC的jvm参数?
native-image
/AOT编译。除此之外,您可能想要使用-client
。 - dan1st