空間站

          北極心空

            BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
            15 Posts :: 393 Stories :: 160 Comments :: 0 Trackbacks

          優化 Java 垃圾收集器改進系統性能

          developerWorks
          文檔選項
          將此頁作為電子郵件發送

          將此頁作為電子郵件發送

          未顯示需要 JavaScript 的文檔選項


          拓展 Tomcat 應用

          下載 IBM 開源 J2EE 應用服務器 WAS CE 新版本 V1.1


          級別: 高級

          李 曉華 (xiaohual@cn.ibm.com), IBM CDL ODSC部門工程師

          2006 年 11 月 30 日

          在系統的性能測試過程中,當系統的處理能力有某種變化趨勢時, 除了關于等待隊列、執行線程,EJB 池以及數據庫連接池和 Statement Cache 方面的調優外,還要考慮到 Java 垃圾收集器(Garbage Collection,本文簡稱 GC)對系統性能的影響。本文介紹了如何分析系統的處理能力和 GC 之間的關系,以及如何通過改進 JVM 的配置來優化 GC,以提高系統的性能。

          項目背景

          某個大型項目的 CPU100% 的壓力性能測試, 用以檢查在系統運行環境不正常的情況下,系統可以運行到何種程度。測試過程是: 請求測試的模擬器向系統不斷發出大量請求, 系統接受由模擬器發出的請求,然后將請求置于一個任務池中,如果當前有空閑的線程,則該線程會從任務池中取出一個任務進行處理,如果沒有空閑的線程,則該任務一直會待在任務池中,直到有空閑的線程來處理它。因此,任務池的隊列的長度從某種意義上可以代表整個系統的處理能力,任務池隊列的長度用 Q 值來表示,如果 Q 值超出了一定限額,將會有流量控制的線程將超出限額的待處理任務丟棄,以保證系統的穩定性。

          整個測試要求得到系統所在服務器的負載達到將近 100% 時,系統的吞吐量,相應時間以及在超負荷下業務請求成功率。

          問題現象描述

          在測試過程中,任務池中累積的任務數起伏很大,正常時累積的任務數很小,但是每隔一段時間會累積大量的任務。由于累積的任務數超出任務池流量控制所定義的限額,所以每隔一段時間,大量的待處理任務被清除。因此測試結束后得到的在超負荷下業務請求成功率也不是很理想。

          應用服務器的物理部署

          一臺AIX服務器(4CPU,4GMemory)來部署本Web應用程序;Web應用程序部署在中間件應用服務器上;部署了一個節點(Node),只配置一個應用服務器實例(Instance),沒有做Cluster部署。





          回頁首


          分析

          檢測WebSphere Application Server上的Web Container,EJB Container , ORB Service,數據庫連接池等設置均合理,然后懷疑問題的現象是不是與系統GC有關。當前Java Virtual Machine的配置為: Initial Heap Size:256 , Maximum Heap Size: 3072。

          為了驗證任務池中累積的任務數的大幅度變化和系統GC是否存在一定的關系,通過對任務池的累積任務數和系統GC進行采樣, 將采樣后的數據進行分析,用以得出二者的關系。采樣時遵循Nyquist采樣定例: 采樣頻率要大于被采集對象的頻率的2倍。 否則,采樣點很可能每次位于被采集對象的波形的某個點上,從而不能正確反映被采集對象的變化規律。

          采樣

          通過觀察,發現任務池的任務數目(以下用Q值代替)的變化周期大概是5到6秒,因此根據Nyquist采樣定例,采樣的時間間隔不能超過2-3秒,所以按照每秒來采樣。 測試時間是3分鐘,采樣180次,系統的當前負載率是99%。采樣圖如下所示:


          圖一 任務池Q值的采樣圖
          圖一 任務池Q值的采樣圖

          由于系流量控制要求的限額是450個任務,也就是任務池中最多能累積450個任務,當任務池中累積的任務數超過450時,多余的任務會被流量控制直接丟棄,從上圖可以看出,系統的Q值在很多時刻都大于450,因此多次被丟棄任務,從而導致了任務請求成功率不高。

          系統GC的采樣

          1: 在WebSphere Administrative Console上, 點擊進入:Servers, 然后Application servers > server1 > Process Definition > Java Virtual Machine, 在Configuration面板上,選上Verbose garbage collection選項。


          圖二 WebSphere Application Server的JVM配置示圖
          圖二 WebSphere Application Server的JVM配置示圖

          2:進入<%WebSphere Application Server的安裝目錄%>/profiles/<%所在的profiles%>/logs/ <%所在的Server%>, 可以看到native_stderr.log文件,將其清空

          3:在高負載的條件下,進行高壓測試3分鐘

          4:將native_stderr.log文件拷貝出來,用GCCollector工具進行分析,其中native_stderr.log文件上記錄了系統GC的數據。

          5:安裝GCCollector工具: 下載完GCCollector.zip后,解壓縮,將里面Lib里的3個文件 jfreechart-1.0.0-rc1.jar,jcommon-1.0.0-rc1.jar 和GCCollector.jar拷貝至JRE的lib目錄下,然后在命令行控制臺上進入JRE的安裝目錄,而后運行: java -classpath jfreechart-1.0.0-rc1.jar;jcommon-1.0.0-rc1.jar -jar GCCollector.jar。

          接著可以看到GCCollector的用戶界面,在它的Parser菜單中選擇JRE的版本,而后在File菜單中選擇并打開剛才拷出的native_stderr.log文件。

          下圖是在高負載情況下,系統在當前配置下的GC分析圖。


          圖三 系統的GC分析圖
          圖三 系統的GC分析圖

          由圖三可以看出,系統沒有內存泄漏的現象,每次GC所花的時間為220ms左右,從GCCollector的Spreadsheet可以查到,GC的時間周期為5-6 s,每次具體GC發生的時間,每次GC所花的時間。

          6:同樣遵循Nyquist采樣定例,對GC進行采樣,采樣后的數據同任務池中Q值的采樣數據進行比較和分析,得出兩者之間存在著密切的關系。下圖為任務池Q值和GC數據采樣分析圖,由圖中可以看出,每次任務池的Q值大幅度增長時,系統剛好發生GC。二者的時間和周期幾乎可以完全匹配。 因此可以初步下一個結論,由于系統的GC,導致了系統在某些時刻不能有足夠的能力來處理請求,因此任務池的Q值在這些時候會因為任務的大量累積而巨幅漲大,即而超出限額的任務被流控所清除,導致了在超負荷下任務請求成功率不是很理想。


          圖四 任務池Q值和GC數據采樣分析圖
          圖四 任務池Q值和GC數據采樣分析圖




          回頁首


          解決方法

          當前的GC發生的頻率和每次所花的時間還算正常,但是如果每次GC所花的CPU時間能減少,就能空出系統更多的能力處理任務池里的任務,用以降低任務池中的任務數,使得Q值基本上位于任務池的限額以下,這樣可以提高在超負荷下業務請求的總的成功率。

          當前Java Virtual Machine的配置為: Initial Heap Size:256 , Maximum Heap Size: 3072。相對而言, Maximum Heap Size設的有點偏大。對于不同的應用程序,最優化堆大小的設置都有可能不同。堆設置變大,GC的頻率會降低,應用程序會運行更長的時間后,才會進行GC,帶來的就是每次GC也會花更長的時間。從而GC調用占用系統更長的時間,使系統沒有足夠的能力處理請求,使得此刻任務池中的任務累積很多,Q值很大,形成很高的峰值,超過流量控制的限額,超過限額數的任務被流量控制給直接丟棄,從而導致總的成功率不高。

          因此,必須降低堆大小,使得GC的頻率增大,每次GC所花時間降低,從而降低Q的峰值,使之位于系統的流量控制的范圍之內,從而提高業務請求的總的成功率。

          當前的流量控制所允許的峰值是450,因此我們需要通過試驗來驗證,堆大小降低到什么值時,Q值的峰值將低于450,以保證總的成功率。 同時在峰值低于450的條件下,什么樣的堆大小設置可以讓系統的性能最佳。 因為如果堆設置過小,會使得對象可分配空間變小,從而會頻繁的使用垃圾收集機制來釋放內存空間,而每次垃圾收集,都會耗用一定的系統資源。所以,我們要通過試驗和監控數據,設法使的我們所設置的堆大小能夠使得我們的程序運行最優化。

          通過多次試驗,我們得出結論:當Java Virtual Machine的配置為: Initial Heap Size:512 , Maximum Heap Size: 1024時,該系統性能最佳。

          從WebSphere Administrative Console上,依次點擊Servers->Application Servers,然后選擇需要的server,接著點擊Process Definition->Java Virtual Machine,而后在那里設置Initial Heap Size:512和Maximum Heap Size: 1024。這時的配置對于該應用系統相對較為合理。這時再次分析3分鐘內的GC的數據,從下圖可以看出,GC的周期縮短了,每1-2秒就會發生一次GC,但是每次GC所花費的CPU時間降低了,平均130ms左右。


          圖五 改進JVM配置后的GC分析圖
          圖五 改進JVM配置后的GC分析圖

          相應地,在JVM配置改進后,對任務池的Q值再進行一次采樣,并且和改進前的采樣值進行比價,采樣圖如下圖六所示,改進后任務池的Q值分布在50-450之間,數值的起伏相對改進前要均衡些。不再出現忽然間Q值大小漲到500以上的情況,基本在流控的限制范圍之類,進而提高了在超負荷下業務請求的總的成功率。


          圖六 改進JVM配置后和改進前的Q值采樣比較圖
          圖六 改進JVM配置后和改進前的Q值采樣比較圖




          回頁首


          總結

          通過本文,我們可以看到系統JVM的配置和系統的性能有著比較大的關系,特別當系統的處理能力成某種變化趨勢時,要考慮到系統GC對系統性能的影響,為了找到兩者的關系,可以通過采樣,圖形比較來進行分析。如果發現二者之間有密切的聯系,可以考慮對JVM的配置進行優化,比如:對最優化堆的大小進行調整。

          對于不同的應用程序,最優化堆大小的設置都有可能不同。如果堆設置較大,可能導致GC的次數變少,但每次GC所花的時間很長,從而導致系統的處理能力抖動很大。此外如果堆設置過大,會占用過多的內存,使內存資源耗盡,從而會頻繁的進行IO操作來使用虛擬內存。 如果堆設置較小,可能導致GC變的頻繁,但每次GC所花的時間不會太長,每次GC對系統的性能影響相對也會小些。但是如果堆設置過小, 會使得對象可分配空間變小,從而會頻繁的GC來釋放內存空間,而每次GC,都會耗用一定的系統資源。因此,要通過試驗和監控數據,設法使的我們所設置的堆大小能夠使得系統運行最優化。



          參考資料



          關于作者

          李曉華, IBM CDL ODSC部門工程師,參與了中國電信3G大型項目. 寫作經歷:曾在國家核心期刊《計算機集成制造》(CIMS)發表文章:《面向異構過程庫的過程搜索方法與系統研究》。Email: xiaohual@cn.ibm.com

          posted on 2006-12-05 14:45 蘆葦 閱讀(401) 評論(0)  編輯  收藏 所屬分類: JAVA
          主站蜘蛛池模板: 蒙阴县| 郯城县| 读书| 睢宁县| 灵寿县| 托克逊县| 景东| 将乐县| 九寨沟县| 五常市| 宾阳县| 西宁市| 阿尔山市| 祁门县| 济阳县| 德州市| 灌南县| 中方县| 台山市| 潮安县| 渝中区| 大方县| 湛江市| 盘山县| 张家口市| 琼结县| 临沂市| 马公市| 札达县| 五河县| 高碑店市| 衡阳市| 巴彦县| 丁青县| 阿拉善右旗| 即墨市| 福泉市| 景泰县| 蛟河市| 璧山县| 甘洛县|