2017-04-14 70 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