我正在使用提供REST API的应用程序。它仅适用于GET请求,通常花费最多100毫秒来处理最繁重的请求。
最近我们开始面临一个问题,即堆不时被填满,而且完整的GC需要花费大量时间,这确实会影响我们的客户。
从我的角度来看,这个应用程序应该在工作一开始就促进Old Gen中的一些对象,之后所有新对象都应该从Eden或Survivor空间中删除。因此,完整的GC绝不会来。然而,有些物品会被提升为Old Gen,这对我来说真的很困惑。
其他一些发现:
那么,请你指点一下:
如果您需要其他信息,请与我们联系。
修改:
JVM参数(已更新):
-XX:MaxPermSize=512m -Xmx7g -Xmn4g -verbose:gc -Xloggc:gc.log -XX:+PrintGCDetails -XX:+PrintTenuringDistribution
申请日志:
Desired survivor size 520617984 bytes, new threshold 15 (max 15)
[PSYoungGen: 3235245K->231763K(3665920K)] 3942774K->939308K(4760064K), 0.0905430 secs] [Times: user=0.31 sys=0.00, real=0.09 secs]
603.561: [GC
Desired survivor size 521142272 bytes, new threshold 15 (max 15)
[PSYoungGen: 3369299K->330881K(3684864K)] 4076844K->1038442K(4779008K), 0.1343473 secs] [Times: user=0.51 sys=0.00, real=0.13 secs]
606.347: [GC
Desired survivor size 506462208 bytes, new threshold 15 (max 15)
[PSYoungGen: 3507329K->215655K(3685376K)] 4214890K->923233K(4779520K), 0.0925060 secs] [Times: user=0.36 sys=0.00, real=0.09 secs]
609.084: [GC
Desired survivor size 492306432 bytes, new threshold 15 (max 15)
[PSYoungGen: 3392103K->213344K(3713536K)] 4099681K->920945K(4807680K), 0.0802729 secs] [Times: user=0.30 sys=0.00, real=0.08 secs]
重要细节:
即使我只用1个线程(每个请求消耗~10 MB)开始性能测试,Old Gen仍在不断增长:
如果我启动GC它会成功清理内存
如果我进行堆转储Mat Analyzer(或Yourkit)再次显示80%的对象无法访问
答案 0 :(得分:1)
如果您的任期阈值迅速降至1,则听起来您正在使用其他参数导致此问题。除了日志记录选项和最大堆之外,我会尝试删除所有其他调整参数,并且只有在您确定它们真正有用时才添加每个参数。你设置的越多,你获得一些奇怪行为的可能性就越大。您可以尝试强制终止阈值,但我怀疑这只会隐藏您的问题。
所需幸存者大小341835776字节,新阈值1(最多15)
为了增加幸存者的数量以避免完全幸存者触发一个完整的GC,幸存者大小或仅仅一代人正在使用整个年轻空间。
我会尝试让年轻一代更大。你需要一个至少你的幸存者空间的伊甸园,所以你的年轻人应该至少1 GB,理想情况下要大几倍。我会尝试4 GB年轻或2 Gb,具体取决于你有多少空间。 e.g。
-Xmn2g -Xmx5g
或
-Xmn4g -Xmx7g
如果你有足够的内存,例如64 GB或更多,我会尝试更大像
-Xmn24g -Xmx32g
并减少年轻空间,如果它似乎没有帮助。