JVM 的功能与相同的标志非常不同

JVM is functioning very differently with same flags

我创建了测试应用程序(内部有 Sheduler 每 20 毫秒运行一次,有 reads/writes 到数据库)并将其部署在两台不同 PC 上的 Glassfish 服务器上。两者都有相同的(从一台 PC 复制到另一台)Glassfish(两者都有最新的 JAVA 版本)服务器,带有以下标志:-XX:+DisableExplicitGC, XX:MaxGCPauseMillis=200, -Xmx512m, -Xms512m, - XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC, -server...

第一台 PC 有 8GB 内存,i5 CPU (2.5 GHz) 和 WIN 8.1 64 位 OS。

这是第一台 PC 的 GC 日志的图形表示(30 小时后):

如您所见,GC 性能约为 12000 MB/s,吞吐量为 99.93%,较小的 GC 暂停时间约为 20 毫秒,每 30 秒发生一次。此时发生了na major GC(但发生在8小时后)。在前 30 小时内,老年代从 90 MB 增加到 160 MB。

第二台 PC 有 1GB RAM,Athlon 64 X2(双核)CPU 和 WIN XP 32 位。这是第二台 PC 的 GC 日志的图形表示(30 小时后):

如您所见,GC 性能约为 4000 MB/s,吞吐量为 99.91%,较小的 GC 暂停时间约为 100 毫秒,每 50 秒发生一次。这个时候有na major GC(4天了还是没发生)。在前 30 小时内,老年代从大约 70 MB 增加到 75 MB。

我的问题是:为什么在第二种情况下升级到老年代比第一种情况小得多?这意味着当第一种情况下的主要 GC 在 40 小时后触发时,主要 GC 不会在相当长的一段时间内触发(也许永远不会)。在这两种情况下,应用程序都在做同样的事情,所以我不明白为什么 JVM 使用相同的标志运行起来会有如此大的不同。我不知道在第一种情况下有什么好处(更多对象提升到老年代)如果这意味着必须发生主要 GC 而在第二种情况下不必发生主要 GC。如果两台服务器上的应用程序以相同的速度执行(每 20 毫秒写入 DB,然后从同一个 DB tanle 读取一些),那么从幸存者 space 提升到老年代有什么好处。与第一种情况(30 秒)相比,第二种情况下的次要 GC 更少(50 秒)。我希望更好的 PC 会有更好的结果,但现在我什至不知道哪个更好......第一种情况的唯一主要优势是更高的 GC 性能速度,因此次要 GC 完成得更快。谢谢大家澄清为什么这样做。

I would expect than better PC would have much better results but now I don't even know which one is better...

更好是主观的。取决于您是否需要吞吐量(CPU 周期花费的 GC 的一小部分)、可持续的分配率、低暂停时间或低占用空间。通常在这些目标之间进行权衡。

G1GCs 是一种复杂的自调整野兽,在不同情况下表现不同。因此,除非确实存在您想避免的有问题的行为,否则问题出在哪里?它只是以不同的方式完成工作。

如评论中所述,如果您只是想满足自己的好奇心,可以通过将 -XX:+PrintFlagsFinal 附加到选项和 运行 差异来比较 VM 标志。它们可能完全不同,因为 32 位和 64 位系统有不同的默认值。