【发布时间】:2011-10-30 04:32:59
【问题描述】:
我正在使用Play! Framework 构建一个Java Web 应用程序。我在playapps.net 上托管它。我一直对提供的内存消耗图表感到困惑。这是一个示例:
该图表来自一段持续但名义上的活动。我没有采取任何措施来触发内存衰减,所以我认为这是因为垃圾收集器运行时几乎达到了允许的内存消耗。
我的问题:
- 假设我的应用程序没有有内存泄漏对我来说公平吗,因为看起来垃圾收集器在运行时正确回收了所有内存?
- (来自标题)为什么java要等到最后一秒才能运行垃圾收集器?随着内存消耗增长到图表的前四分之一,我发现性能显着下降。
- 如果我上面的断言是正确的,那么我该如何解决这个问题?我在 SO 上阅读的其他帖子似乎反对对
System.gc()的调用,范围从中立(“它只是运行 GC 的请求,因此 JVM 可能会忽略你”)到完全反对(“依赖于 @987654327 的代码@ 从根本上被破坏了”)。还是我在这里偏离了基地,我应该在自己的代码中寻找导致这种行为和间歇性性能损失的缺陷?
更新
我已经在 PlayApps.net 上针对这个问题展开了讨论,并在这里提到了一些要点;特别是@Affe 关于完整 GC 设置的评论非常保守,@G_H 关于初始和最大堆大小设置的评论。
这是link to the discussion,不过很遗憾,您需要一个 playapps 帐户才能查看它。
我收到反馈后会在这里报告;非常感谢大家的回答,我已经从他们那里学到了很多东西!
分辨率
Playapps 支持仍然很棒,但对我没有太多建议,他们唯一的想法是,如果我广泛使用缓存,这可能会使对象的存活时间超过需要的时间,但事实并非如此。我仍然学到了很多东西(哇哦!),我给了@Ryan Amos 绿色的支票,因为我接受了他的建议,即每半天打电话给System.gc(),目前效果很好。
【问题讨论】:
-
我不太了解 play 框架,无法就其内存占用给您一个明确的答案,但是 SAP 提供了一个很好的工具来分析内存分配,现在在 eclipse.org/mat 我认为这可能会有所帮助您可以对内存泄漏做出断言而不是假设。
-
可能导致性能问题的一件事是交换;如果您没有足够的物理内存用于该堆(例如,它是一个共享机器,有许多其他进程使用大量内存),将页面交换到磁盘会降低 VM 的性能。
-
@rds Play 以非常小的内存占用而自豪,而 PlayApps.net(我正在使用的托管服务)本身占用的内存比我展示的要小。谢谢MAT推荐,我去看看!
-
另外,我同意 +vanza 关于交换灾难的看法。根据我在 SharePoint 上的(糟糕的)经验,我记得为进程提供过多内存并非总是最佳性能策略。你能改变 JVM 设置并设置 -Xmx 80m,看看它的行为如何?
-
@Raedwald:我以前没听说过。 32 位 JVM 的最大堆大小有一个限制,远低于如今的平均 RAM 内存容量。 64 位 JVM 不再是这种情况。但即便如此,如果主机上正在运行许多进程并且其内存已满,则交换将开始发生。这是由操作系统处理的,JVM 对此一无所知。它只会分配内存,不知道其中一些可以映射到磁盘。
标签: java memory memory-management playframework