2013-11-14 66 views
4

我有一個Java應用程序運行在獨立的JVM中。應用程序在一個或多個套接字上偵聽數據,對數據進行排隊,並調度線程將數據從隊列中拉出並保留。數據很寬,每條記錄超過700個數據元素,儘管所有數據元素都是小字符串,整數或長整型。高對象複製時間導致長垃圾回收暫停G1GC

該應用程序可以平穩運行一段時間,有時會持續30分鐘到一個小時,但隨後我們會遇到一次或多次長時間垃圾回收暫停。大部分暫停時間用於對象複製時間。系統時間相對於其他集合也很高。

這裏是JVM細節:

java version "1.7.0_03" 
Java(TM) SE Runtime Environment (build 1.7.0_03-b04) 
Java HotSpot(TM) 64-Bit Server VM (build 22.1-b02, mixed mode) 

以下是JVM選項:

-XX:MaxPermSize=256m -XX:PermSize=256m -Xms3G -Xmx3G -XX:+UseG1GC -XX:-UseGCOverheadLimit 

的方法是使用taskset至4個內核(全部在同一插座上),但幾乎沒有使用2-其中。這個盒子上的所有進程都被固定到他們自己的核心(0個未使用的1個)。該機器具有足夠的可用內存(20 + G),頂部顯示使用2.5G RES內存的過程。

下面是一些GC日誌輸出...

[Object Copy (ms): 2090.4 2224.0 2484.0 2160.1 1603.9 2071.2 887.8 1608.1 1992.0 2030.5 1692.5 1583.9 2140.3 1703.0 2174.0 1949.5 1941.1 2190.1 2153.3 1604.1 1930.8 1892.6 1651.9 

[Eden: 1017M(1017M)->0B(1016M) Survivors: 7168K->8192K Heap: 1062M(3072M)->47M(3072M)] 

[Times: user=2.24 sys=7.22, real=2.49 secs] 

爲什麼對象複製時間和sys時間是如此之高,如何糾正它的任何想法?日誌中有大量垃圾收集,幾乎相同的伊甸園/倖存者/堆大小隻需要10或20毫秒。

回答

0

需要 3千兆字節的堆?隨着堆棧變得越來越大,垃圾收集暫停會變得更長,因爲(儘管不那麼頻繁)當最終需要GC時,還有更多工作要做。

看起來你是鎖定堆在3演出通過設置一個最小值。如果應用程序不需要3次演出,這將迫使它無論如何都要使用這些功能,並且最終確實需要收集3G時導致暫停。

我花了相當一段時間來調整Eclipse IDE的響應速度,並且很早就發現緊湊堆大小比「大」更好的「低暫停」特性。

除了JVM堆設置,您可以確保您的代碼「空出」數據元素&收集項目,因爲它們被丟棄。

這是java.util集合包中的標準做法,但也許您有可從中受益的代碼。這700多條記錄尤其可以成爲這種做法的候選人,這有助於簡化GC的工作,並且可以更好地從「次要GC」掃描中清除。

+0

謝謝您的輸入。是的,它確實需要3G。收集的頻率將取決於地區填滿的速度。 G1GC專門爲更大的堆設計,並且是一個增量收集器。 「G1的第一個重點是爲運行需要大堆並且GC延遲有限的應用程序的用戶提供解決方案。這意味着堆大小約6GB或更大,並且穩定和可預測的暫停時間低於0.5秒。「 – user2992915

+0

嘗試在對象處理完成後將它們」置零「,然後特別注意解除鏈接結構。如果你能夠充分打破所有結構,它可以幫助GC在之前/或不需要這種重大停頓的情況下清理掉碎片。 –

1

3GB不是一個大堆,倖存者的大小也很小。還有其他的核心運行嗎?你生成多少垃圾,多久收集一次?您也可以嘗試不使用G1GC。