新聞中心
近年來,我們專注于提供全系列企業級性能管理方案和相關的IT服務,在幫助用戶提高業務效率和整體生產力的同時,降低運營和運維成本。
返回列表
首頁 / 新聞資訊 / 公司動態
GC日志分析與策略選擇的最佳方案
來源:東方龍馬   日期:2019-03-22

 

概述


1WAS環境OOM


基于WebSphere Application Server(Was) 構建的企業應用,時常會出現性能問題,在嚴重的情況下還會發生內存溢出,這是一件很讓人惱怒的事情。在Was運行的時候,內存溢出,會生成大量的溢出文件,如Javacore, Heapdump等文件,占用了大量的磁盤空間。在這種情況下,時常會出現一連串的系統問題,如部署在Was的所有應用服務都報錯,Was連控制臺也無法訪問等。


為解決問題,我們通常會選擇重新啟動整個Was服務器,然后分析運行日志SystemOut.log、SystemErr.log、native_stdout.log、native_stderr.log 和系統內存溢出的時候產生的Javacore、Heapdump文件來尋找出問題。


2堆內存


應用服務器在運行過程中需要創建很多對象,而在應用服務器的堆空間大小有限的情況下,請求進程不斷申請空間來創建與存放對象,在達到上限時而服務器又沒能釋放出空間來處理申請空間的請求就會出現內存溢出情況。這就像吹氣球,當氣球中的氣體到達一定程度時,氣球就會被撐爆。通常在投入生產的系統中,出現溢出一般都是對象分配不合理導致的。


3對象與對象管理


在Java的體系中,所有的類作為一個對象(包括Jdk本身提供的類,應用中由開發人員編寫的類),都是直接或者間接繼承了Java.lang.object產生的。這些類被創建的時候都會向Jvm堆申請一定的內存空間存放,因此在Jvm堆空間里會存放各式各樣的對象,有的是靜態類型,有的是私有類型等等,而這些對象都是通過垃圾收集器進行管理的。


垃圾收集器(Garbage Collection,我們通常稱之為GC)。Java語言通過垃圾收集器管理內存中的對象。但如果對象分配與使用不合理,也會導致垃圾回收在性能上拖Jvm的后腿。為了解決性能問題,GC則是一個讓我們不能忽視的問題。根據不同的應用場景,選擇適合的GC策略,可以幫助系統性能在一定程度上得到顯著的優化。



垃圾回收策略


垃圾收集器為了快速清除在JVM堆中不再使用的對象,從而釋放出空間來供其他請求創建對象,常見的方法有引用計數方法和對象引用遍歷方法等算法,目前主流的方法為對象引用遍歷方法。通過這些高效的算法實現的GC策略有許多種,他們都是針對各種應用場景而產生的,我們可以通過在JVM啟動參數中設置,來調整GC策略。


1策略種類及功能說明


適用IBM SDK5.0以上版本


序號

策略

選項

描述

備注

1

針對吞吐量進行優化

-Xgcpolicy:optthruput

WAS默認策略。對于吞吐量比短暫的 GC 停頓更重要的應用程序,通常使用這種策略。每當進行垃圾收集時,應用程序都會停頓。


2

針對停頓時間進行優化

-Xgcpolicy:optavgpause

通過并發地執行一部分垃圾收集,在高吞吐量和短 GC 停頓之間進行折中。應用程序停頓的時間更短。


3

分代并發

-Xgcpolicy:gencon

以不同方式處理短期存活的對象和長期存活的對象。采用這種策略時,具有許多短期存活對象的應用程序會表現出更短的停頓時間,同時仍然產生很好的吞吐量。

推薦使用(從WAS8開始默認采用)

4

子池

-Xgcpolicy:subpool

采用與默認策略相似的算法,但是采用一種比較適合多處理器計算機的分配策略。建議對于有 16 個或更多處理器的 SMP 計算機使用這種策略。這種策略只能在 IBM System i? System p? 和 System z?平臺上使用。需要擴展到大型計算機上的應用程序可以從這種策略中受益。


 

2選擇合適的GC策略


一般是通過吞吐量和停頓時間兩個參數來衡量GC效率是否適合當前應用系統。


? 吞吐量

是應用程序處理的數據量。衡量吞吐量的標準是與具體應用程序相關的。


? 停頓時間

是垃圾收集器將所有應用程序線程停下來,從而對堆進行收集所經歷的時間。


 為了選擇適合的GC策略,可以在業務應用系統打開詳細垃圾回收,收集系統在運行過程中的GC日志,通過分析GC日志,來判斷當前GC策略是否符合當前應用系統。合理的創建使用對象,選擇適合的GC策略,往往能讓性能有一定的提高,也減少了內存溢出的可能性,或者縮短系統停頓的時間。



WAS分代策略


1GC日志分析


以下是一段發生在IBM SDK5.0版本上配置了分代并發策略所產生的GC日志。


<!—距離上次GC間隔時間為6.787 秒 

<af> 表示本次垃圾回收是因為分配失敗而引發的,如果標簽開頭寫著sys,則表示應用中有顯示調用GC,如System.gc()。一般情況下不建議顯示調用GC,當然也可以通過配置防止顯示GC, 在JVM啟動參數中加入-Xdisableexplicitgc參數屏蔽顯式GC。

Type=“nursery” :這次GC的類型是新生代方式,因為新生代的分配失敗而進行垃圾回收了。

 Id=”3365”代表GC發生在新生代,已經重復執行了3365次

timestamp:GC的執行時間

-->

<af type="nursery" id="3365" timestamp="三  1月 06 16:09:03 2010" intervalms="6787.454">

   <!—這里記錄需要申請的堆大小為710824b 約694KB -->

<minimum requested_bytes="710824" />

  <!—GC準備開始前 使用時間為 0.224秒 -->

<time exclusiveaccessms="0.224" />

  <!—GC前堆空間使用情況,可以看到剩余567408B,不能滿足空間的申請要求了,申請空間是710824B,因此就需要進行GC -->

  <nursery freebytes="567408" totalbytes="42694656" percent="1" />

   <!--   GC前的堆空間情況,JVM堆大小為1.2左右了,空閑的空間為650mb左右,大致空閑空間為48%

Tenured:長存(tenured) 區域

Soa:小對象使用區域;就是 “正常的” 堆。所有對象最初都分配給小對象區域,但是如果小區域已經分配完了,則將大于 64KB 的對象分配給大對象區域。

Loa:大對象使用區域;大對象區域是堆中保留給大對象分配的一小片區域。如果應用程序不需要大對象區域(也就是應用程序不分配任何大對象),內存管理例程會快速將大對象區域縮減為空,這樣,整個堆都可以供 “正常的” 分配使用。

 -->

  <tenured freebytes="666933424" totalbytes="1365881856" percent="48" >

    <soa freebytes="654641328" totalbytes="1353589760" percent="48" />

    <loa freebytes="12292096" totalbytes="12292096" percent="100" />

  </tenured>

 <!—GC后堆空間使用情況 -->

<!—詳細gc情況 

type="scavenger":垃圾回收類型為清理過程。

id="3365": 意為執行力3365次清理,并且沒有發生過全局GC,如 <gc type=”global”>。

<flipped objectcount="15558" bytes="3973128" />:說明將要把15558個存活下來的對象被復制到了幸存區(survivor space)

<tenured objectcount="14791" bytes="14233400" />:說明將要把14791個對象則經過多次幸存區的復制,被轉移到了長存區(tenured)

 

<scavenger tiltratio="65" />:清理的傾斜比率為65%

<refs_cleared soft="73" weak="61" phantom="0" />:清理了存在引用對象的數目. 弱引用為61、軟引用為73,和虛引用為0. 弱引用、軟引用和虛引用允許靈活的緩存,能夠改進應用程序的內存特性。如果引用對象過多大于1000,GC停頓時間就會受到影響。因此我們需要檢查是否存在過多的應用對象。

<finalization objectsqueued="40" />:收尾器,存在需要在GC后,要調用的自定義方法的對象。

 

-->

  <gc type="scavenger" id="3365" totalid="3709" intervalms="6788.531">

    <flipped objectcount="15558" bytes="3973128" />

    <tenured objectcount="14791" bytes="14233400" />

    <refs_cleared soft="73" weak="61" phantom="0" />

    <finalization objectsqueued="40" />

<scavenger tiltratio="65" />

 

<!—GC后的情況

nursery區

1、清理了出空閑堆大小為39108112b  約為38191.515625KB,約為37MB

   2、 總大小為44144640B,約43110KB 約為42MB

-->

<nursery freebytes="39108112" totalbytes="44144640" percent="88" tenureage="1" />

 

<!—

Tenured長存區總大小為1365881856B,約為1.27GB

   空閑堆大小為 651143448B  620MB

 -->

 

    <tenured freebytes="651143448" totalbytes="1365881856" percent="47" >

      <soa freebytes="638851352" totalbytes="1353589760" percent="47" />

      <loa freebytes="12292096" totalbytes="12292096" percent="100" />

    </tenured>

    <time totalms="25.029" />

  </gc>

 

<!--這里再次打印需要申請的堆大小為710824b 約694KB -->

<minimum requested_bytes="710824" />

 

<!--通過比較,就可以知道當前次的GC情況,及堆空間的使用率

<time totalms="26.386" /> 總的GC時間為26.386ms

 -->

  <nursery freebytes="38397288" totalbytes="44144640" percent="86" />

  <tenured freebytes="651143448" totalbytes="1365881856" percent="47" >

    <soa freebytes="638851352" totalbytes="1353589760" percent="47" />

    <loa freebytes="12292096" totalbytes="12292096" percent="100" />

  </tenured>

  <time totalms="26.386" />

</af>

<!-- 經過垃圾回收,新生代的空間剩余86%,因為分配失敗發生在新生代,進行的是快速的Minor gc,所以長存區的可用空間依然是47%,這次回收的時間為26.386ms。而

在長存區發生的是Major gc,回收時間一般要長于Minor gc,一般健康的JVM 環境Minor gc:Minor gc=1:10。   -->


打開詳細垃圾回收,我們就可以獲得詳細垃圾回收情況,根據以上的GC日志的分析,我們則可以了解到系統GC提供了什么樣的信息給我們。通過這些信息,我們可以分析得出當前GC策略是否需要調整。(當然這個與您實際生產得出的GC日志分析結果有關)。


2調整GC策略判斷標準


在分析的過程里,我們需要著重查看以下幾點:


? GC頻率:

多長時間執行一次GC,如果GC頻繁的話,則需要檢查系統現在的運行情況是否合理


? GC類型+GC申請空間大小+新生代空間大小:

分析GC是否合理


? 各分代區域的大小:

檢查當前JVM堆的使用是否合理,新生代的空間大小是否符合當前業務場景要求。長存區的空間大小是否合理,再聯合JVM配置的堆配置大小分析,堆的使用是否存在問題,因為雖然進行了GC,但堆空間的使用如不能滿足要求的話,易導致系統出現全局GC,在壓力過大的情況下還會內存溢出。


? 重點檢查GC過程中長存區的變化:

是否存在大對象,如果有的話,可以考慮-Xlp參數優化


? GC過程中是否清理了過多引用對象:

如有則需要檢查應用


? GC整個過程消耗的時間是否過長:

過長的GC會直接影響到系統的性能,當然這個也與GC類型有關,全局GC,清理長存區的GC時間相對會長點,但是這些類型的GC不會很頻繁。


通過詳細分析GC日志,從而協助我們進一步了解JVM堆的使用情況,最后得出當前GC策略是否符合業務應用使用場景,而更換其他GC策略則需要配合當前業務場景與JVM堆使用情況去選擇適合的GC策略。 


3IBM Java虛擬機其他選項


適合IBM JDK 設置參數簡單介紹:


序號

選項

描述

11

-Xlp

此設置與IBM JVM配合使用,以使用大頁16MB來分配堆

22

Xlp64k

此參數與IBM JVM配合使用,以使用64K字節頁大小來分配堆

33

-Xnoclassgc

關閉類垃圾回收,可以消除由于多次裝入和卸載同一個類而造成地開銷

44

-Xnocompactgc

該參數完全關閉壓縮。雖然在性能方面有短期的好處,最終應用程序堆將變得支離破碎,即使堆中有足夠的自由空間也會導致 OutOfMemory 錯誤

55

-Xcompactgc

使用該參數將導致每個垃圾收集周期都執行壓縮,無論是否有必要。JVM 在壓縮時要做大量的決策,在普通模式下會推遲壓縮

66

-Xgcthreads

該參數控制 JVM 在啟動過程中創建的垃圾收集幫助器線程個數。對于 N-處理器機器,默認的線程數為 N-1。這些線程提供并行標記和并行清理模式中的并行機制



|  北京    |    上海    |   廣州    |   成都    |


4008-906-960



4008-906-960

全國免費咨詢電話
  • 官方微博
  • 官方微信
Copyright 1998-2016 版權所有 北京東方龍馬軟件發展有限公司 京ICP備14000200號-1
上海时时彩加盟