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有更詳細的圖文解釋: 性能
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問題。
它的原理:
在Arena Allocation方案中,數組的大小影響空間連續性,越大內存連續性越好,但內存平均利用率會下降。
HBase的解決方案-MSLAB
MSLAB,全稱是 MemStore-Local Allocation Buffer,是Cloudera在HBase 0.90.1時提交的一個patch裏包含的特性。它基於Arena Allocation解決了HBase因Region flush致使的內存碎片問題。
MSLAB的實現原理(對照Arena Allocation,HBase實現細節):
優點:
開啓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夠大了