2017-02-14 52 views
2

我有一個在tomcat上運行的web應用程序,它的最大堆大小設置爲8GB。什麼導致完整的GC運行?

以下是我的vm參數。

export CATALINA_OPTS="$CATALINA_OPTS -Xms512m -Xmx8192m -XX:+UseConcMarkSweepGC" 

如果沒有用戶登錄到應用程序,那麼不可清除的內存(位於垃圾收集之後)非常低(約1GB)。

在這種情況下,如果我觀察使用jconsole內存的增長模式,我看到約4GB恆定的內存增長,然後垃圾收集器運行和內存再次下降至約1 GB。這種模式繼續下去,如果沒有用戶獲取登錄。

如果我登錄了GC數據,我看到類似下面。

2017-02-14T15:30:44.553+0530: 591.922: [GC (Allocation Failure) [PSYoungGen: 1501051K->631966K(1833472K)] 2392189K->1523112K(3030016K), 1.5100144 secs] [Times: user=1.49 sys=0.01, real=1.51 secs] 
2017-02-14T15:31:20.335+0530: 627.705: [GC (Allocation Failure) [PSYoungGen: 1553054K->595007K(1842176K)] 2444200K->1570521K(3038720K), 1.3050284 secs] [Times: user=1.27 sys=0.04, real=1.31 secs] 
2017-02-14T15:33:33.682+0530: 761.052: [GC (Allocation Failure) [PSYoungGen: 1516095K->556800K(1842176K)] 2491609K->1596474K(3038720K), 1.6957154 secs] [Times: user=1.67 sys=0.03, real=1.69 secs] 
2017-02-14T15:33:35.378+0530: 762.748: [Full GC (Ergonomics) [PSYoungGen: 556800K->365446K(1842176K)] [ParOldGen: 1039673K->1196476K(2018304K)] 1596474K->1561923K(3860480K), [Metaspace: 70472K->70472K(1114112K)], 11.2779843 secs] [Times: user=11.13 sys=0.09, real=11.28 secs] 
2017-02-14T15:34:56.232+0530: 843.602: [GC (Allocation Failure) [PSYoungGen: 1286534K->216613K(1842176K)] 2483011K->1609875K(3860480K), 1.4938761 secs] [Times: user=1.45 sys=0.05, real=1.50 secs] 

如可以看到的那樣,有時一個完整GC進行,相比於較小的GC已經採取了相當長的時間(11秒),(〜1秒)。

因爲所有其他線程被GC期間暫停,如果用戶嘗試一個完整的GC期間訪問Web應用程序,服務器沒有響應。

我想知道的是什麼觸發了這個完整的GC?根據日誌,小gc事件是由於分配失敗造成的,Full GC由於Ergonomics而導致。這是什麼意思?

有沒有什麼辦法可以防止滿GC在這種情況下發生?還有很多可用的堆空間,我想延遲Full GC發生,直到由於較小的GC而沒有顯着的內存減少。

+1

能否請您添加要使用(XMS,MaxGCPauseMillis,其集熱器,...),加上您的服務器的物理內存的所有GC-VM相關的選項。如果你想暫停時間很短,那麼延遲完整的gcs並不是一種可行的方式,因爲暫停會更少但更長。所以在我看來,你的堆配置得太大了,無法實現你想要實現的目標(再加上你使用了錯誤的collection-algorithm)。 –

+0

@ piet.t,添加到問題的虛擬機選項 –

+0

應用程序可能在代碼中某處顯式調用'System.gc()'調用。我看到CMS收集器有點瘋狂,並且在調用System.gc()後總是執行停止全局GC。您可以通過'-XX:+ DisableExplicitGC' JVM選項使GC忽略此類調用。 –

回答

0

解決您的首要問題(服務器檔口花了垃圾收集,由於過多的時間),這可能是用於一些原因是由於錯誤的垃圾收集器。垃圾收集調整記錄在here。通過Garbage-First collector,您可以設置任何可以接受的暫停(默認值爲200毫秒,這對服務器來說應該不是什麼大問題)。

0

我想指出你的Parallel Collector鏈接。 「人體工程學」是一種利用應用程序的特定行爲自動調節收集器的方法。

大多數情況下,自動調整是好的。在你的情況下,它似乎是以太長的GC結束。您可以通過調整收集器的參數來修復它。

引用文檔:

最大垃圾回收暫停時間

最大停頓時間目標與命令行選項-XX規定:MaxGCPauseMillis =。這被解釋爲希望暫停時間爲毫秒或更短的提示;默認情況下,沒有最大暫停時間目標。如果指定了暫停時間目標,則會調整與垃圾收集相關的堆大小和其他參數,以嘗試使垃圾收集暫停時間短於指定值。這些調整可能會導致垃圾收集器降低應用程序的整體吞吐量,並且不能始終滿足所需的暫停時間目標。

吞吐量

吞吐量的目標中的時間來測量執行垃圾回收與垃圾收集的外花的時間(被稱爲應用時間)。目標由命令行選項-XX:GCTimeRatio =指定,該選項將垃圾收集時間與應用程序時間的比率設置爲1 /(1 +)。

例如,-XX:GCTimeRatio = 19設置垃圾收集總時間的1/20或5%的目標。默認值爲99,導致垃圾收集時間的目標爲1%。

足跡

最大堆足跡使用選項-Xmx指定。另外,只要其他目標得到滿足,收集器就有一個隱含的目標,即儘可能減小堆的大小。

+0

-XX:MaxGCPauseMillis對我來說看起來是一個不錯的選擇,但它能夠最小化完整GC所需的時間嗎?在我的情況下,小GC運行速度非常快,但全GC大約需要10倍。我懷疑-XX:MaxGCPauseMillis是否可以把這個降到1秒左右。 –

+0

@LahiruChandima當然不,當然,它會盡量尊重設定的時間,但這只是一個提示。如果在定製GC之後仍然存在問題,則應該調查爲什麼有太多垃圾對象以及爲什麼不能在更小的時間範圍內完成。 –

+0

我將添加-XX:MaxGCPauseMillis並檢查。實際上我並不認爲整個GC的持續時間較長是由於大量的對象數。正如我通過jconsole所觀察到的那樣,當小GC發生時,它會在不到2秒的時間內移除大約3GB的垃圾對象。 –

相關問題