1

有一个 java 服务器端应用程序。线程数高达1000。该应用程序强烈使用NIO进行通信,JINI等。

您是否认为每分钟分配/取消分配 400 兆字节对于 java 应用程序来说是好的(可接受的)?

提出这个问题的原因 - 随着时间的推移,可用内存量变得越来越少:存在一些内存泄漏(每天几兆),使用的内存量也取决于要做的工作量(应用程序缓存了一些东西)。因此,可能存在 <= 100 兆可用内存的情况。GC 当然会变得疯狂,因为它的活动变得非常需要。(建议重启运行时间为生产中的一个月)

来自 VisualVM 的堆分配统计信息

4

2 回答 2

2

400 MB/秒的垃圾是非常糟糕的。

400 MB/分钟的垃圾对于您的应用程序来说可能是可以的。

我会尝试将 Eden 大小-XX:NewSize=增加到 1g、2g 或 4g,看看这是否会提高性能。

如果这比您拥有的 CPU 数量多,我会尝试估计您拥有的活动线程数。

于 2012-10-10T12:54:50.707 回答
1

线程数最多为 1000。

这可能太多了,IMO。根据您的平台和-Xss.

您是否认为每分钟分配/取消分配 400 兆字节对于 java 应用程序来说是好的(可接受的)?

那应该不是问题。事实上,从性能图来看,GC 看起来只是 CPU 时间的一小部分……而只是可用时间的一小部分。

问这个问题的原因 - 随着时间的推移,可用内存量变得越来越少:存在一些内存泄漏(每天几兆),

好吧,您应该考虑追踪并修复这些泄漏。

... 使用的内存量也取决于要做的工作量(应用程序缓存一些东西)。

答案可能是增加堆大小。而且(令人惊讶的是)增加堆大小可以减少垃圾收集所花费的时间百分比。(虽然并发收集器和非常大的堆可能存在问题......)

因此,可能存在 <= 100 兆可用内存的情况。GC 当然会变得疯狂,因为它的活动变得非常需要。

是的。这很可能是您的存储泄漏的结果,而不是高分配率。随着 JVM 越来越接近 Heap 耗尽,GC 将花费越来越多的总时间来运行。这是不可避免的。(GC 大部分时间都在处理不是垃圾的对象。随着可回收空间的比例下降,回收该空间的成本会上升。)

有一个以-XX:+UseGCOverheadLimitJVM 开关的形式解决此问题的方法。这使用了“在抛出 OutOfMemory 错误之前限制虚拟机在 GC 中花费的时间比例的策略”。. 基本上,它导致不可避免的 OOME在您的服务器陷入性能不断下降的死亡螺旋之前被抛出......

(建议重启运行时间为生产中的一个月)

...或修复内存泄漏!!!

于 2012-10-10T13:19:26.930 回答