我创建了测试应用程序(内部有Sheduler,每20毫秒运行一次,对数据库有读/写操作),并将其部署在两台不同PC上的Glassfish服务器上。两者都有相同的(从一台PC复制到另一台PC)Glassfish(两者都有最新的JAVA版本)服务器,带有以下标志:-XX: DisableExplicitGC,XX:MaxGCPauseMillis=200,-Xmx512m,-Xms512m,-XX:UseCompressedClassPointers-XX:UseCompressedOops-XX:useg1 GC,-server...
第一台PC有8GB的RAM,i5 CPU(2.5 GHz)和WIN 8.1 64位操作系统。
如您所见,GC性能约为12000 MB/s,吞吐量为99,93%,轻微的GC暂停约为20ms,每30秒发生一次。此时发生了重大GC(但发生在8小时后)。在最初的30小时内,旧一代从90 MB增加到160 MB
如您所见,GC性能约为4000 MB/s,吞吐量为99,91%,轻微的GC暂停约为100毫秒,每50秒发生一次。此时发生了重大GC(4天后仍未发生)。在最初的30小时内,旧一代的容量从大约70 MB增加到75 MB
我在这里的问题是:为什么第二种情况下晋升到老一代的几率比第一种情况小得多?这意味着当第一个案例中主要GC在40小时后被触发时,主要GC在相当长的时间内(可能永远不会)不会被触发。应用程序在这两种情况下做着同样的事情,所以我不明白为什么JVM在相同的标志下会有如此大的不同。我不知道在第一种情况下(更多的对象升级到老一代)有什么好处,如果这意味着主要GC必须发生,而在第二种情况下主要GC不必发生。如果两个服务器上的应用程序以相同的速度执行(每20毫秒写入数据库,然后一些从同一个数据库谭乐读取),那么从幸存者空间升级到老一代有什么好处?第二种情况下的小GC(50秒)也比第一种情况(30秒)更少。我期望比更好的电脑会有更好的结果,但现在我甚至不知道哪一个更好...第一种情况的唯一主要优势是更高的GC性能速度,因此较小的GC执行速度更快。感谢大家澄清为什么这样做。
我希望更好的PC会有更好的结果,但现在我甚至不知道哪一个更好。。。
更好是主观的。这取决于您是否需要吞吐量(花费在GCing上的CPU周期的一部分)、可持续的分配率、低暂停时间或低占用空间。通常在这些目标之间有一个权衡。
G1GCs是一个复杂的自调优怪兽,在不同的环境下表现不同。所以除非你真的想避免有问题的行为,否则问题在哪里呢?它只是工作方式不同。
正如在评论中提到的,如果你只是想满足你的好奇心,你可以通过将-XX:PrintFlagsFinal
附加到选项来比较VM标志,并运行一个diff。它们可能非常不同,因为32位和64位系统的默认值不同。