java GC CMS-initial-mark减慢了高负载tomcat生产服务器上的查询速度

时间:2014-05-08 20:43:13

标签: java performance tomcat garbage-collection jvm

我有提供Web请求的java tomcat应用程序。它应该尽快执行每个Web请求。每秒我收到大约4个请求。我在优化servlet方面做了很多工作。现在它通常在不到100毫秒的时间内为每个请求服务。但有时请求在200ms后提供。如果我重新运行这些慢速请求,它们会再次快于100毫秒。我已启用GC日志记录,并发现几乎总是在每个“慢”请求之前我有CMS-initial-mark冻结JVM:

[GC [1 CMS-initial-mark: 1411302K(1415616K)] 1912881K(2029056K), 0.3224110 secs] 
[Times: user=0.00 sys=0.00, real=0.32 secs]

大多数情况下,请求执行时间与GC收集时间大致相同。我使用8核服务器和32GB的RAM。我的JVM设置是:

-Xmx2G -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails. 

我的操作系统是最新的Debian,默认设置。除了mongodb,没有其他进程在运行。 top命令输出中显示的唯一进程是java,它使用~100%的CPU(我有8个CPU,所以只有1/8的负载)。

我该如何克服这个问题?还能诊断出什么?

3 个答案:

答案 0 :(得分:0)

初始标记的时间非常长。这表明发生了一些奇怪的事情。它可能是太大而无法编译的方法(因为它超过8 KB)

你可能有大量的终身对象指向短期对象,但这不太可能导致如此长的延迟。这会对所有CPU造成负担。

重要的是你似乎在捆绑一个CPU,这表明一个非常特殊的问题(比如一个超大的方法)

我会考虑增加伊甸园的大小,以减少过早的促销活动。这可能有所帮助,或者根据你正在做的事情使情况变得更糟。

与此同时,我会尝试并行收集器。您可能会发现它可以更好地处理您的用例。

BTW,如果您需要100毫秒,您可能会减少产生的垃圾量。我会在内存分析器中查看您的分配并尝试减少它们。

答案 1 :(得分:0)

在日志中记下user=0.00 sys=0.00。这意味着不是GC需要花费这么多时间 CPU处于空闲状态,但应用程序冻结,可能是因为外部活动(如I / O或交换)。

你告诉mongodb正在运行。这不是磁盘I / O的原因吗?我在Linux中经历了类似的问题,在密集磁盘操作期间长时间停止,直到我切换到deadline I/O scheduler

答案 2 :(得分:0)

如果有人感兴趣,我可以告诉我如何解决问题。我为-Xmx5G增加了一点内存。然后我意识到对mongodb进行的查询有一个额外的java层morphia,它使用@Reference对每个嵌套文档进行额外的查询。我已经重写了瓶颈mongodb请求,问题已经消失。无论如何,谢谢你的想法。