1. 程式人生 > >java程式效能優化讀書筆記-垃圾回收

java程式效能優化讀書筆記-垃圾回收

衡量系統性能的點
  • 執行速度:即響應時間
  • 記憶體分配:記憶體分配是否合理,是否過多消耗記憶體或者存在記憶體洩露
  • 啟動時間:程式從啟動到正常處理業務需要的時間
  • 負載承受能力:當系統壓力上升,系統執行速度和響應時間上升曲線是否平緩

系統調優層次
  • 系統設計調優
  • 程式碼調優
  • jvm調優
  • 資料庫調優
  • 作業系統調優

垃圾回收基礎

垃圾回收演算法:

  • 引用計數法:每個物件都有一個引用計數器,當被一個物件引用的時候計數器+1,當引用失效的時候計數器-1,當計數器為0的時候就可以被回收掉。這種演算法的缺陷是,不能解決迴圈引用的問題,當A\B相互引用的時候,各自的引用計數器都為1,但是他們都沒有被第三個物件所引用,所以是可以被回收掉的。由於由這種缺陷,引用計數法不適合JVM的垃圾回收。

  • 標記-清除演算法:標記清除法是現代垃圾回收演算法思想的基礎。從根節點開始,通過標記根節點開始所有可達的物件,標記完成後,對未標記的物件進行清除。這種演算法的缺點是,清除後會出現不連續的記憶體區域。不連續的記憶體空間效率比連續的記憶體空間要低。

  • 複製演算法:把記憶體區域分成2塊。一塊是正在使用的,一塊是沒有在使用的。當進行垃圾回收的時候,把存活的物件從正在使用的區域複製到非正在使用的區域,然後清除正在使用區域的所有物件,交換2個記憶體的角色完成垃圾回收。這樣可用區域的記憶體就連續了。如果垃圾物件多餘存活物件,這種方式效果就比較好。

    java新生代垃圾序列回收器使用了複製演算法的思想。

  • 標記壓縮演算法:適合老年代回收演算法。在標記清除法的基礎上做了優化。當需要回收的物件比較少的時候,這種演算法比較高效。標記完後,把存活的物件壓縮到記憶體的一端,然後把垃圾物件清理,這樣就避免了不連續區域。

  • 增量演算法:對於大部分垃圾回收演算法,垃圾回收的時候會stop the world,所有應用的執行緒都會掛起,導致停頓。增加的話,是分割槽域垃圾回收,減少垃圾回收的範圍,然後再間歇執行下應用程式。

  • 分代:將記憶體區域根據物件特點分成幾塊,不同的塊使用不同的垃圾回收演算法。在Hot Spot虛擬機器中,所有新建的物件都放到新生代,當一個物件經過幾次回收仍然存活就放入老年代

記憶體區域 使用的演算法
新生代 複製演算法
老年代 標記壓縮演算法

JVM調優常見案例
  • 大物件進入老年代:新生的大物件如果放在新生帶可能會擾亂新生代的記憶體回收,因為新生代如果被大物件擠滿了,新產生的物件都會被擠過去老年代, -XX:PretenureSizeThreshold 設定大物件直接進入老年代的閾值。 如果進入了老年代,又比較短命的話,標記壓縮演算法又會很不利,所以如果短命的大物件太多,對垃圾回收是一種災難。

  • 設定進入老年代的年齡:新生代進入老年代和年齡有關。新物件會放在eden區,如果經過一次回收仍然存活,則被放入survivior區,物件年齡增加1。如果年齡達到的閾值就會被挪到老年代。-XX:MaxTenuringThreshold 設定最大年齡。

  • 穩定與震盪的堆大小: 穩定的堆大小會減少GC的次數,因此有的人會設定最小堆記憶體和最大堆記憶體成一樣的值。但是GC堆大的話也會影響單次GC的時間。因此出了Xmx和Xms外還提供了以下引數。當Xmx和Xms一樣的時候以下引數無效。

引數 作用
-XX:MinHeapFreeRatio:40 堆空間最小空閒比例,預設是40。當空閒的小於40%的時候,會擴大堆空間,確保程式空閒的時候震盪不會太大。
-XX:MaxHeapFreeRatio:70 堆空間最大空閒比例,預設是70。當空閒的空間大於70%的時候,會壓縮堆空間。

實用案例

  • 吞吐量優先案例(32核,4G)
啟動引數 引數解析
-Xmx3800m -Xms3800m 減少堆震盪和頻繁GC。吞吐量大,記憶體一般都會維持在較高水平
-Xss128k 減少執行緒棧大小,剩餘的系統記憶體支援更多的執行緒。
-Xmn2g 設定新生代大小
-XX:UseParallelGC 新生代使用並行回收器
-XX:ParallelGCThreads=20 設定垃圾回收執行緒總數
-XX:UseParallelOldGC 老年代也使用並行回收器
  • 使用大葉案例:在Solaris系統中,jvm支援大頁使用 -XX:LargePageSizeInBytes=256m

  • 降低停頓案例

啟動引數 引數解析
-XX:ParallelGCThreads=20 設定垃圾回收執行緒總數
-XX:UseParallelGC 新生代使用並行回收器
-XX:UseConcMarkSweepGC 老年代使用CMS收集器降低停頓
-XX:SurvivorRatio=8 eden區:survivor區 = 8:1 稍大的survivor區,可以提高在新生代回收宣告週期較短的物件的可能性,避免進入老年代
-XX:TargetSurvivor=90 設定survivor的可使用率為90%,預設是50%,提高了survivor區的實用率
-XX:MaxTenuringThreshold=31 設定年輕代進入老年代的年齡,預設是15,這裡設定成31,儘可能地將物件儲存在新生代