利用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, 感谢原做者分享。
相关文章
相关标签/搜索