我创建了测试应用程序(Sheduler内部每20ms运行一次,对DB有读/写)并将其部署在两台不同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位操作系统。
以下是第一台PC的GC日志的图形表示(30小时后):
正如您所看到的,GC Peformance大约为12000 MB / s,吞吐量为99,93%,较小的GC暂停时间约为20ms,并且每30秒发生一次。此时有一个主要的GC(但它发生在8小时后)。在前30个小时,老一代从90 MB增加到160 MB。
第二台PC拥有1GB内存,Athlon 64 X2(双核)CPU和WIN XP 32位。这是第二台PC的GC日志的图形表示(30小时后):
正如您所看到的,GC Peformance大约为4000 MB / s,吞吐量为99,91%,较小的GC暂停时间约为100毫秒,并且每50秒发生一次。此时有一个主要的GC(4天后仍未发生)。在前30个小时,老一代从大约70 MB增加到75 MB。
我的问题是:为什么第二种情况下对老一代的晋升比第一种情况要小得多?这意味着当40小时后触发第一种情况下的主要GC时,主要GC不会被触发很长时间(可能永远不会)。应用程序在两种情况下都做同样的事情所以我不明白为什么JVM在相同的标志下运行的方式如此之差。我不知道在第一种情况下有什么好处(更多的对象升级到老一代),如果这意味着在第二种情况下必须发生主要GC,则不必发生主要的GC。如果两台服务器上的应用程序以相同的速度执行,则从幸存者空间升级到老一代的好处是什么(每20ms写入一次DB,然后从同一个DB读取一些数据)。第二种情况下的次要GC比第一种情况(30秒)更少(50秒)。我希望PC会有更好的效果,但现在我甚至不知道哪一个更好......只有第一种情况的主要优点是更高的GC性能速度,所以较小的GC做得更快。谢谢大家澄清为什么这样做。
答案 0 :(得分:3)
我希望PC会有更好的效果,但现在我甚至不知道哪一个更好......
更好是主观的。取决于您是否需要吞吐量(用于GCing的CPU周期的一小部分),可持续分配率,低暂停时间或低占用空间。通常在这些目标之间进行权衡。
G1GCs是一种复杂的,自杀的野兽,在不同的环境下表现不同。因此,除非您想避免实际存在问题,否则问题出在哪里?它的工作方式不同。
如评论中所述,如果您只是希望满足您的好奇心,可以通过将-XX:+PrintFlagsFinal
附加到选项并运行差异来比较VM标记。它们可能完全不同,因为32位和64位系统的默认值不同。