我正在 glassfish 服务器上运行一个应用程序,并且有以下 JVM 设置(我认为这与我的问题相关):
-Xmx512m -XX:NewRatio=2 -XX:+UseParallelOldGC -XX:+UseParallelGC
所有其他设置均为默认设置。过去 48 小时我一直在使用 JMC(Java Mission Control)测试服务器性能,我注意到:PS Old Gen 大约有 341 MB 堆,PS Eden 大约有 143MB 堆,PS Surviovor 大约有 13MB 堆(是这个吗?)足够了还是我应该使用不同的 SurvivorRatio?)
图表显示,一开始,java 堆有大约 200MB 的分配空间,但每次 Full GC 之后它都会增长,所以现在约为 450MB,甚至使用的堆(每次 Full GC 之后)也会下降到 100MB 左右,然后慢慢增长,直到下一个次要的GC/full GC...为什么提交的java堆(红线)增加?这是正常行为吗?当达到512MB时会停止吗?我应该使用 -Xms512m 提交的 java 堆从一开始就是 512MB 吗?
现在关于垃圾收集: Minor GC (PS Scavenge) 大约每 1 分钟运行一次,持续时间约为 10-30 毫秒。 Full GC (PS MarkSweep) 大约每 14-18 小时运行一次,第一次持续时间为 200 毫秒,但最后一次持续时间为 20 秒(我不知道为什么持续时间有这么大的差异)!我想知道这是否可以以及如何获得更好的结果?我应该使用
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC
还是什至 -XX:+UseG1GC
?如果我使用这些 GC 中的任何一个,我是否必须增加最大堆大小(我读到 UseG1GC 仅适用于较大的堆)?除了 GC 类型之外,我是否还必须更改任何其他设置(例如 SurvivorRatio、NewRation...)?
JMC中的GC Duration是否等于停止世界暂停时间(或者暂停时间更短)?那么,如果我的完整 GC 的 GC 持续时间为 20 秒,这是否意味着我的服务器在 20 秒内没有响应?我的服务器上有 JAX-RS,并且我使用 ajax 每 10 秒调用其中一个(超时为 10 秒),这意味着至少有 2 个调用不会成功?在这种情况下ajax调用的状态是什么(可能是错误)?我必须警告用户有关错误调用的信息,而且我不知道在这种情况下,如果错误是由于 GC 暂停而导致的,该怎么办......
如果我有 -Xmx1024m(比现在大两倍),完整 GC 会很少见,但会持续更长时间吗?
我读了很多关于 JVM 和 JVM GC 的文章,但我仍然不知道我必须做什么才能使所有设置对于我的应用程序都是最佳的(我担心最后 20 秒长的 GC 持续时间)...
谢谢您的回答!
Full GC (PS MarkSweep) 大约每 14-18 小时运行一次,第一次持续时间为 200 毫秒,但最后一次持续时间为 20 秒
尝试通过
-XX:MaxGCPauseMillis
设置暂停时间目标。
我应该使用 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC 还是 -XX:+UseG1GC?
这些当然是一个选择,但由于并行收集器似乎能够最初提供不错的延迟,并且随着旧一代的增加只会变得更糟,你可能不需要
图表显示,一开始,java 堆有大约 200MB 的分配空间,但每次 Full GC 之后它都会增长,所以现在约为 450MB,甚至使用的堆(每次 Full GC 之后)也会下降到 100MB 左右,然后慢慢增长,直到下一个次要的GC/full GC...为什么提交的java堆(红线)增加?
因为您使用的是并行收集器,它以吞吐量为主要目标(如果没有指定限制,可能会损害内存占用或延迟)。当大量垃圾积累时,它可以通过很少收集来提供最高的吞吐量。
通过为其提供暂停时间目标,如果堆变得太大而无法满足暂停时间目标,它将停止增长堆。
如果我有 -Xmx1024m(比现在大两倍),完整 GC 会很少见,但会持续更长时间吗?
有可能,但是一旦无法满足
MaxHeapFreeRatio
目标,GC就会停止增长堆。
-XX:NewRatio=3 增加数字,直到暂停缩短到系统可接受的水平。