2017-04-14 133 views
2

我试图调整某种高负载应用程序,即将数据从一个云端流式传输到另一个预处理端口。 我的应用程序的具体内容是广泛的内存使用和低CPU消耗。 我用jconsole监控了应用程序,并且发现了一些有趣的图片--CPU加载了15%,我仍然捕捉到了内存不足的错误。内存不足,CPU消耗低

从jconsole手动触发“执行GC”会清除所有代中的大量内存,所以我假设应用程序中没有内存泄漏。我试图在单个虚拟CPU之间切换到具有各种GC的多CPU(-XX:+ UseG1GC; -XX:+ UseParallelGC,无需其他调整),并且图片实际上是相同;

  • 那么,为什么GC不使用CPU来释放内存?
  • 我们可以调整GC以进行更频繁/正确的工作吗?

运行指标: enter image description here

系统配置: enter image description here

+1

是什么“内存不足”是指在这种情况下?你会得到OuOfMemoryException?这似乎不大可能,因为您说手动调用GC时内存已被释放。如果你没有得到例外,你的问题是什么? – Axel

+2

也许你正在分配一些如此之大的东西,甚至GC也不会清除足够的内存,在这种情况下,我认为系统甚至可以毫无困难地执行GC操作。 – john16384

+1

获取堆转储,看看有什么在内存中 – Vipin

回答

1

我觉得我应该分享我的调查结果。

“内存不足” - 这是我从DevOps-guy获得的,我首先想到的是 - OutOfMemoryException。所以,谢谢Alex对clarifying question

在我的情况下这是来自底层操作系统的docker环境中的OOMKill。我为容器分配了1G,并限制了736米的java堆大小。 但我的应用程序使用netty分配自己的内存缓冲区绕过堆。所以,当更多的连接出现时,netty会分配更多的直接缓冲区,从而导致OOMKill尽管健康的堆。

+0

我想这是一个很好的解释,你可以接受你自己的答案。 – maaartinus

2

GC在需要应用程序释放内存时运行。 GC操作昂贵,只有在需要时才能运行。 我不知道你为什么试图通过运行GC来关联CPU利用率。 CPU利用率与运行GC应用程序无关。 如果VM线程决定GC运行,它将暂停所有正在运行的应用程序线程(Safepointing)并允许GC执行操作,因此Java Java使用的CPU数量保持不变,与您剩下多少CPU无关。

有许多GC标志可以用来微调你的应用程序,我不能建议任何不确定你的应用程序是什么?

可能下面的链接将帮助您 http://www.cubrid.org/blog/dev-platform/how-to-tune-java-garbage-collection/ https://confluence.atlassian.com/enterprise/garbage-collection-gc-tuning-guide-461504616.html

你应该知道你在哪里OOM,老一代,元空间中,代码生成或基于本机上,你可以微调与堆的选择越来越

+0

嗨Fairoz,谢谢你的回答和链接!我将CPU使用量与GC活动相关联,因为我们可能会遇到诸如“超出GC开销限制”之类的问题。当用户线程停止并且GC正在处理内存时 - 它将消耗CPU。所以这个组合对我来说似乎很奇怪:内存问题和较低的CPU消耗。 – Silk0vsky

+0

此外,我[意识到](http://stackoverflow.com/questions/43407713/out-of-memory-with-low-cpu-consumption/43492305#43491520),这是不是GC相关的问题 – Silk0vsky