利用Arena Allocation避免HBase觸發Full GC

利用Arena Allocation避免HBase觸發Full GC

Ken Wu's Blog 2011-06-21 86 閱讀

Arena Allocation,是一種GC優化技術,它能夠有效地減小因內存碎片致使的Full GC,從而提升系統的總體性能。本文介紹Arena Allocation的原理及其在Hbase中的應用-MSLAB。 java

背景

假設有1G內存,我順序建立了1百萬個對象,每一個對象大小1K,Heap會被漸漸充滿且每一個對象以建立順序相鄰。此時,若是我釋放50萬個奇數對象,即 1 3 5 7後,剩餘空間會多出500M,而這段內存空間就再也不連續了。問題出現?
若是我打算new一個2K大小的對象,JVM將無從分配它,由於找不到連續可用的內存空間來容納這個對象,就算Heap當時還有500M的剩餘空間,也無能爲力。最終,JVM會選擇觸發Full GC從新壓縮內存使之連續,而後再分配。 數組

結論:觸發Full GC,並不僅有在內存滿或達到觸發比例的時候,還有多是由於內存碎片。 緩存

產生內存碎片的主要緣由是: app

  • 分配的大小不一。
  • 分配的空間不連續。

如何檢測因內存碎片觸發了Full GC?
經過啓動java時,添加 -XX:PrintFLSStatistics=1 參數來打印每次gc先後的Heap餘量。較大的餘量,能夠懷疑Heap中存在內存碎片過多。
另外這篇blog有更詳細的圖文解釋: 性能

http://www.cloudera.com/blog/2011/02/avoiding-full-gcs-in-hbase-with-memstore-local-allocation-buffers-part-2/ 優化

HBase中的內存碎片

HBase爲了提升寫入性能,爲每一個region添加了一個內存寫緩存-Memstore。當單個Memstore的大小達到 memstore.size或Heap內存達到 hbase.regionserver.global.memstore.upperLimit/lowerLimit百分比限制時,就會觸發整個 region的flush,最終將全部數據寫入HDFS並釋放region下全部Memstores佔用的內存(GC不必定及時)。 spa

Region flush致使內存碎片的示意圖: server

左邊五光十色的是不一樣的region在內存中的位置,它是無序的,由於客戶端的請求是無規律的。此時假設黃色的region觸發了flush,那麼右邊將會出現與之對應的多個空洞,即內存碎片。??這張圖以region爲粒度,僅僅是爲了更直觀地表示這種現象。真實場景中,這些空洞是更細粒度的KeyValue級對象,它能直接致使建立對象時觸發Full GC。 對象

Arena Allocation blog

Arena Allocation是一種非傳統的內存管理方法。它經過順序化分配內存,內存數據分塊等特性使內存碎片粗化,有效改善了內存碎片致使的Full GC問題。

它的原理:

  • 建立一個大小固定的bytes數組和一個偏移量,默認值爲0。
  • 分配對象時,將新對象的data bytes複製到數組中,數組的起始位置是偏移量,複製完成後爲偏移量自增data.length的長度,這樣作是防止下次複製數據時不會覆蓋掉老數據(append)。
  • 當一個數組被充滿時,建立一個新的數組。
  • 清理時,只須要釋放掉這些數組,便可獲得固定的大塊連續內存。

在Arena Allocation方案中,數組的大小影響空間連續性,越大內存連續性越好,但內存平均利用率會下降。

HBase的解決方案-MSLAB

MSLAB,全稱是 MemStore-Local Allocation Buffer,是Cloudera在HBase 0.90.1時提交的一個patch裏包含的特性。它基於Arena Allocation解決了HBase因Region flush致使的內存碎片問題。

MSLAB的實現原理(對照Arena Allocation,HBase實現細節):

  • MemstoreLAB爲Memstore提供Allocator。
  • 建立一個2M(默認)的Chunk數組和一個chunk偏移量,默認值爲0。
  • 當Memstore有新的KeyValue被插入時,經過KeyValue.getBuffer()取得data bytes數組。將data複製到Chunk數組起始位置爲chunk偏移量處,並增長偏移量=偏移量+data.length。
  • 當一個chunk滿了之後,再建立一個chunk。
  • 全部操做lock free,基於CMS原語。

優點:

  • KeyValue原始數據在minor gc時被銷燬。
  • 數據存放在2m大小的chunk中,chunk歸屬於memstore。
  • flush時,只須要釋放多個2m的chunks,chunk未滿也強制釋放,從而爲Heap騰出了多個2M大小的內存區間,減小碎片密集程度。

開啓MSLAB

hbase.hregion.memstore.mslab.enabled=true // 開啓MSALB
hbase.hregion.memstore.mslab.chunksize=2m // chunk的大小,越大內存連續性越好,但內存平均利用率會下降
hbase.hregion.memstore.mslab.max.allocation=256K // 經過MSLAB分配的對象不能超過256K,不然直接在Heap上分配,256K夠大了

詳見:http://www.cloudera.com/blog/2011/03/avoiding-full-gcs-in-hbase-with-memstore-local-allocation-buffers-part-3/

Arena Allocation,是一種GC優化技術,它能夠有效地減小因內存碎片致使的Full GC,從而提升 […]
做者:Ken Wu's Blog
just another software engineer blog
原文地址: 利用Arena Allocation避免HBase觸發Full GC, 感謝原做者分享。
相關文章
相關標籤/搜索