我们正在使用 IBM JDK 1.4.2 在 AIX 上的 Websphere Portal Server 5.1 上将一个相当复杂的应用程序作为 portlet 运行。在我们的生产系统上,我可以在详细的 GC 日志中看到一个奇怪的行为。在一段时间的正常行为之后,系统可以开始快速分配越来越大的块。系统开始花费超过 1000 毫秒来完成每个 GC,但是分配块的速度非常快,以至于分配失败之间只有 30 毫秒的间隔。
- 每个分配失败比最后一个稍大一些整数 x 1024 字节。例如,您可能有 5 MB,然后不久之后 5 MB + 17 * 1024。
- 这可以持续长达 10 分钟。
- 在停止之前,这些块的大小往往会增长到 8 到 14 MB。
- 这是一个四核系统,我假设它现在花费超过 95% 的时间进行 GC,其中三个核心等待另一个核心完成 GC。10 分钟。哎哟。
- 显然,此时系统性能会下降。
- 我们有 JSF、hibernate 和 JDBC、Web 服务调用、log4j 输出等等。
我认为这可能是基础设施而不是我们的应用程序代码。如果是循环内的错误字符串连接,我们预计会比 1024 个块有更多的不规则增长。如果是 StringBuffer 或 ArrayList 增长,我们会看到块大小翻倍。这种增长让我想到了日志缓冲或其他东西。在我们的应用程序中我想不出任何分配甚至 1 MB 的东西,更不用说 14。今天我在内存中寻找日志记录备份,然后再刷新到磁盘,但是在这段 GC 颠簸期间的日志记录语句量远不及MB 范围。
很明显,问题在于过多的内存分配,而不是垃圾收集,垃圾收集只是尽力跟上。有些东西正在分配一个大块并试图以太小的增量低效地增长它。
当系统处于负载状态时,有什么想法可能导致所有这些吗?有人看到与 Portal Server 类似的东西吗?
注意:对于任何感兴趣的人来说,原因似乎是偶尔但巨大的数据库查询。罪魁祸首似乎是 Hibernate 或 JDBC 驱动程序。