HBASE-11514 Fix findbugs warnings in blockcache

This commit is contained in:
stack 2014-07-15 07:51:27 -07:00
parent bf2933e08a
commit 96dcd67f56
7 changed files with 138 additions and 129 deletions

View File

@ -117,7 +117,7 @@ public class CacheConfig {
* A float which designates how much of the overall cache to give to bucket cache * A float which designates how much of the overall cache to give to bucket cache
* and how much to on-heap lru cache when {@link #BUCKET_CACHE_COMBINED_KEY} is set. * and how much to on-heap lru cache when {@link #BUCKET_CACHE_COMBINED_KEY} is set.
*/ */
public static final String BUCKET_CACHE_COMBINED_PERCENTAGE_KEY = public static final String BUCKET_CACHE_COMBINED_PERCENTAGE_KEY =
"hbase.bucketcache.percentage.in.combinedcache"; "hbase.bucketcache.percentage.in.combinedcache";
public static final String BUCKET_CACHE_WRITER_THREADS_KEY = "hbase.bucketcache.writer.threads"; public static final String BUCKET_CACHE_WRITER_THREADS_KEY = "hbase.bucketcache.writer.threads";
@ -451,6 +451,22 @@ public class CacheConfig {
@VisibleForTesting @VisibleForTesting
static boolean blockCacheDisabled = false; static boolean blockCacheDisabled = false;
private static long getLruCacheSize(final Configuration conf, final MemoryUsage mu) {
float cachePercentage = conf.getFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY,
HConstants.HFILE_BLOCK_CACHE_SIZE_DEFAULT);
if (cachePercentage <= 0.0001f) {
blockCacheDisabled = true;
return -1;
}
if (cachePercentage > 1.0) {
throw new IllegalArgumentException(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY +
" must be between 0.0 and 1.0, and not > 1.0");
}
// Calculate the amount of heap to give the heap.
return (long) (mu.getMax() * cachePercentage);
}
/** /**
* Returns the block cache or <code>null</code> in case none should be used. * Returns the block cache or <code>null</code> in case none should be used.
* *
@ -460,21 +476,8 @@ public class CacheConfig {
public static synchronized BlockCache instantiateBlockCache(Configuration conf) { public static synchronized BlockCache instantiateBlockCache(Configuration conf) {
if (GLOBAL_BLOCK_CACHE_INSTANCE != null) return GLOBAL_BLOCK_CACHE_INSTANCE; if (GLOBAL_BLOCK_CACHE_INSTANCE != null) return GLOBAL_BLOCK_CACHE_INSTANCE;
if (blockCacheDisabled) return null; if (blockCacheDisabled) return null;
float cachePercentage = conf.getFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY,
HConstants.HFILE_BLOCK_CACHE_SIZE_DEFAULT);
if (cachePercentage <= 0.0001f) {
blockCacheDisabled = true;
return null;
}
if (cachePercentage > 1.0) {
throw new IllegalArgumentException(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY +
" must be between 0.0 and 1.0, and not > 1.0");
}
// Calculate the amount of heap to give the heap.
MemoryUsage mu = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage(); MemoryUsage mu = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
long lruCacheSize = (long) (mu.getMax() * cachePercentage); long lruCacheSize = getLruCacheSize(conf, mu);
int blockSize = conf.getInt("hbase.offheapcache.minblocksize", HConstants.DEFAULT_BLOCKSIZE); int blockSize = conf.getInt("hbase.offheapcache.minblocksize", HConstants.DEFAULT_BLOCKSIZE);
String bucketCacheIOEngineName = conf.get(BUCKET_CACHE_IOENGINE_KEY, null); String bucketCacheIOEngineName = conf.get(BUCKET_CACHE_IOENGINE_KEY, null);
@ -492,26 +495,23 @@ public class CacheConfig {
int writerQueueLen = conf.getInt(BUCKET_CACHE_WRITER_QUEUE_KEY, int writerQueueLen = conf.getInt(BUCKET_CACHE_WRITER_QUEUE_KEY,
DEFAULT_BUCKET_CACHE_WRITER_QUEUE); DEFAULT_BUCKET_CACHE_WRITER_QUEUE);
String persistentPath = conf.get(BUCKET_CACHE_PERSISTENT_PATH_KEY); String persistentPath = conf.get(BUCKET_CACHE_PERSISTENT_PATH_KEY);
float combinedPercentage = conf.getFloat( float combinedPercentage = conf.getFloat(BUCKET_CACHE_COMBINED_PERCENTAGE_KEY,
BUCKET_CACHE_COMBINED_PERCENTAGE_KEY,
DEFAULT_BUCKET_CACHE_COMBINED_PERCENTAGE); DEFAULT_BUCKET_CACHE_COMBINED_PERCENTAGE);
String[] configuredBucketSizes = conf.getStrings(BUCKET_CACHE_BUCKETS_KEY); String[] configuredBucketSizes = conf.getStrings(BUCKET_CACHE_BUCKETS_KEY);
int[] bucketSizes = null; int [] bucketSizes = null;
if (configuredBucketSizes != null) { if (configuredBucketSizes != null) {
bucketSizes = new int[configuredBucketSizes.length]; bucketSizes = new int[configuredBucketSizes.length];
for (int i = 0; i < configuredBucketSizes.length; i++) { for (int i = 0; i < configuredBucketSizes.length; i++) {
bucketSizes[i] = Integer.parseInt(configuredBucketSizes[i]); bucketSizes[i] = Integer.parseInt(configuredBucketSizes[i]);
} }
} }
if (combinedWithLru) {
lruCacheSize = (long) ((1 - combinedPercentage) * bucketCacheSize);
bucketCacheSize = (long) (combinedPercentage * bucketCacheSize);
}
LOG.info("Allocating LruBlockCache size=" + LOG.info("Allocating LruBlockCache size=" +
StringUtils.byteDesc(lruCacheSize) + ", blockSize=" + StringUtils.byteDesc(blockSize)); StringUtils.byteDesc(lruCacheSize) + ", blockSize=" + StringUtils.byteDesc(blockSize));
LruBlockCache lruCache = new LruBlockCache(lruCacheSize, blockSize, true, conf); LruBlockCache lruCache = new LruBlockCache(lruCacheSize, blockSize, true, conf);
lruCache.setVictimCache(bucketCache);
if (bucketCache != null && combinedWithLru) {
GLOBAL_BLOCK_CACHE_INSTANCE = new CombinedBlockCache(lruCache, bucketCache);
} else {
GLOBAL_BLOCK_CACHE_INSTANCE = lruCache;
}
try { try {
int ioErrorsTolerationDuration = conf.getInt( int ioErrorsTolerationDuration = conf.getInt(
"hbase.bucketcache.ioengine.errors.tolerated.duration", "hbase.bucketcache.ioengine.errors.tolerated.duration",
@ -523,6 +523,12 @@ public class CacheConfig {
LOG.error("Can't instantiate bucket cache", ioex); LOG.error("Can't instantiate bucket cache", ioex);
throw new RuntimeException(ioex); throw new RuntimeException(ioex);
} }
if (combinedWithLru) {
GLOBAL_BLOCK_CACHE_INSTANCE = new CombinedBlockCache(lruCache, bucketCache);
} else {
GLOBAL_BLOCK_CACHE_INSTANCE = lruCache;
}
lruCache.setVictimCache(bucketCache);
} }
LOG.info("Allocating LruBlockCache size=" + LOG.info("Allocating LruBlockCache size=" +
StringUtils.byteDesc(lruCacheSize) + ", blockSize=" + StringUtils.byteDesc(blockSize)); StringUtils.byteDesc(lruCacheSize) + ", blockSize=" + StringUtils.byteDesc(blockSize));

View File

@ -698,7 +698,7 @@ public class LruBlockCache implements ResizableBlockCache, HeapSize {
*/ */
static class EvictionThread extends HasThread { static class EvictionThread extends HasThread {
private WeakReference<LruBlockCache> cache; private WeakReference<LruBlockCache> cache;
private boolean go = true; private volatile boolean go = true;
// flag set after enter the run method, used for test // flag set after enter the run method, used for test
private boolean enteringRun = false; private boolean enteringRun = false;
@ -861,7 +861,25 @@ public class LruBlockCache implements ResizableBlockCache, HeapSize {
@Override @Override
public int compareTo(CachedBlock other) { public int compareTo(CachedBlock other) {
return (int)(other.getOffset() - this.getOffset()); int diff = this.getFilename().compareTo(other.getFilename());
if (diff != 0) return diff;
diff = (int)(this.getOffset() - other.getOffset());
if (diff != 0) return diff;
if (other.getCachedTime() < 0 || this.getCachedTime() < 0) {
throw new IllegalStateException("" + this.getCachedTime() + ", " +
other.getCachedTime());
}
return (int)(other.getCachedTime() - this.getCachedTime());
}
@Override
public boolean equals(Object obj) {
if (obj instanceof CachedBlock) {
CachedBlock cb = (CachedBlock)obj;
return compareTo(cb) == 0;
} else {
return false;
}
} }
}; };
} }

View File

@ -259,6 +259,10 @@ public class BucketCache implements BlockCache, HeapSize {
persistencePath + ", bucketAllocator=" + this.bucketAllocator); persistencePath + ", bucketAllocator=" + this.bucketAllocator);
} }
public long getMaxSize() {
return this.cacheCapacity;
}
public String getIoEngine() { public String getIoEngine() {
return ioEngine.toString(); return ioEngine.toString();
} }
@ -1248,7 +1252,25 @@ public class BucketCache implements BlockCache, HeapSize {
@Override @Override
public int compareTo(CachedBlock other) { public int compareTo(CachedBlock other) {
return (int)(this.getOffset() - other.getOffset()); int diff = this.getFilename().compareTo(other.getFilename());
if (diff != 0) return diff;
diff = (int)(this.getOffset() - other.getOffset());
if (diff != 0) return diff;
if (other.getCachedTime() < 0 || this.getCachedTime() < 0) {
throw new IllegalStateException("" + this.getCachedTime() + ", " +
other.getCachedTime());
}
return (int)(other.getCachedTime() - this.getCachedTime());
}
@Override
public boolean equals(Object obj) {
if (obj instanceof CachedBlock) {
CachedBlock cb = (CachedBlock)obj;
return compareTo(cb) == 0;
} else {
return false;
}
} }
}; };
} }

View File

@ -20,89 +20,48 @@
* {@link org.apache.hadoop.hbase.io.hfile.BlockCache}. Caches are configured (and instantiated) * {@link org.apache.hadoop.hbase.io.hfile.BlockCache}. Caches are configured (and instantiated)
* by {@link org.apache.hadoop.hbase.io.hfile.CacheConfig}. See head of the * by {@link org.apache.hadoop.hbase.io.hfile.CacheConfig}. See head of the
* {@link org.apache.hadoop.hbase.io.hfile.CacheConfig} class for constants that define * {@link org.apache.hadoop.hbase.io.hfile.CacheConfig} class for constants that define
* cache options and configuration keys to use setting cache options. Cache implementations * cache options and configuration keys to use setting cache options. Cache implementations
* include the default, native on-heap {@link org.apache.hadoop.hbase.io.hfile.LruBlockCache}, * include the default, native on-heap {@link org.apache.hadoop.hbase.io.hfile.LruBlockCache} and a
* a {@link org.apache.hadoop.hbase.io.hfile.slab.SlabCache} that can serve as an L2 for
* {@link org.apache.hadoop.hbase.io.hfile.LruBlockCache} (hosted inside the class
* {@link org.apache.hadoop.hbase.io.hfile.DoubleBlockCache} that caches blocks in BOTH L1 and L2,
* and on evict, moves from L1 to L2, etc), and a
* {@link org.apache.hadoop.hbase.io.hfile.bucket.BucketCache} that has a bunch of deploy formats * {@link org.apache.hadoop.hbase.io.hfile.bucket.BucketCache} that has a bunch of deploy formats
* including acting as a L2 for LruBlockCache -- when a block is evicted from LruBlockCache, it * including acting as a L2 for LruBlockCache -- when a block is evicted from LruBlockCache, it
* goes to the BucketCache and when we search a block, we look in both places -- or using * goes to the BucketCache and when we search a block, we look in both places -- or
* {@link org.apache.hadoop.hbase.io.hfile.CombinedBlockCache}, as * using {@link org.apache.hadoop.hbase.io.hfile.CombinedBlockCache}, BucketCache is used as
* a host for data blocks with meta blocks in the LRUBlockCache as well as onheap, offheap, and * a host for data blocks with meta blocks in an instance of LruBlockCache. BucketCache
* file options. * can also be onheap, offheap, and file-backed.
* *
* <h1>Which BlockCache should I use?</h1> * <h1>Which BlockCache should I use?</h1>
* BucketCache has seen more production deploys and has more deploy options. Fetching will always * By default LruBlockCache is on. If you would like to cache more, and offheap, try enabling
* BucketCache. Fetching will always
* be slower when fetching from BucketCache but latencies tend to be less erratic over time * be slower when fetching from BucketCache but latencies tend to be less erratic over time
* (roughly because GC is less). SlabCache tends to do more GCs as blocks are moved between L1 * (roughly because GC is less). See Nick Dimiduk's
* and L2 always, at least given the way {@link org.apache.hadoop.hbase.io.hfile.DoubleBlockCache} * <a href="http://www.n10k.com/blog/blockcache-101/">BlockCache 101</a> for some numbers.
* currently works. It is tough doing an apples to apples compare since their hosting classes,
* {@link org.apache.hadoop.hbase.io.hfile.CombinedBlockCache} for BucketCache vs
* {@link org.apache.hadoop.hbase.io.hfile.DoubleBlockCache} operate so differently.
* See Nick Dimiduk's
* <a href="http://www.n10k.com/blog/blockcache-101/">BlockCache 101</a> for some numbers. See
* also the description of <a href="https://issues.apache.org/jira/browse/HBASE-7404">HBASE-7404</a>
* where Chunhui Shen lists issues he found with BlockCache (inefficent use of memory, doesn't
* help w/ GC).
*
* <h1>Enabling {@link org.apache.hadoop.hbase.io.hfile.slab.SlabCache}</h2>
* {@link org.apache.hadoop.hbase.io.hfile.slab.SlabCache} is the original offheap block cache
* but unfortunately has seen little use. It is originally described in
* <a href="http://blog.cloudera.com/blog/2012/01/caching-in-hbase-slabcache/">Caching
* in Apache HBase: SlabCache</a>.To enable it,
* set the float <code>hbase.offheapcache.percentage</code>
* ({@link org.apache.hadoop.hbase.io.hfile.CacheConfig#SLAB_CACHE_OFFHEAP_PERCENTAGE_KEY}) to some
* value between 0 and 1 in
* your <code>hbase-site.xml</code> file. This
* enables {@link org.apache.hadoop.hbase.io.hfile.DoubleBlockCache}, a facade over
* {@link org.apache.hadoop.hbase.io.hfile.LruBlockCache} and
* {@link org.apache.hadoop.hbase.io.hfile.slab.SlabCache}. DoubleBlockCache works as follows.
* When caching, it
* "...attempts to cache the block in both caches, while readblock reads first from the faster
* onheap cache before looking for the block in the off heap cache. Metrics are the
* combined size and hits and misses of both caches." The value set in
* <code>hbase.offheapcache.percentage</code> will be
* multiplied by whatever the setting for <code>-XX:MaxDirectMemorySize</code> is in
* your <code>hbase-env.sh</code> configuration file and this is what
* will be used by {@link org.apache.hadoop.hbase.io.hfile.slab.SlabCache} as its offheap store.
* Onheap store will be whatever the float
* {@link org.apache.hadoop.hbase.HConstants#HFILE_BLOCK_CACHE_SIZE_KEY} setting is
* (some value between 0 and 1) times the size of the allocated java heap.
*
* <p>Restart (or rolling restart) your cluster for the configs to take effect. Check logs to
* ensure your configurations came out as expected.
* *
* <h1>Enabling {@link org.apache.hadoop.hbase.io.hfile.bucket.BucketCache}</h2> * <h1>Enabling {@link org.apache.hadoop.hbase.io.hfile.bucket.BucketCache}</h2>
* Ensure the SlabCache config <code>hbase.offheapcache.percentage</code> is not set (or set to 0). * Read the options and defaults for BucketCache in the head of the
* At this point, it is probably best to read the code to learn the list of bucket cache options * {@link org.apache.hadoop.hbase.io.hfile.CacheConfig}.
* and how they combine (to be fixed). Read the options and defaults for BucketCache in the
* head of the {@link org.apache.hadoop.hbase.io.hfile.CacheConfig}.
* *
* <p>Here is a simple example of how to enable a <code>4G</code> * <p>Here is a simple example of how to enable a <code>4G</code> offheap bucket cache with 1G
* offheap bucket cache with 1G onheap cache. * onheap cache managed by {@link org.apache.hadoop.hbase.io.hfile.CombinedBlockCache}.
* The onheap/offheap caches * CombinedBlockCache will put DATA blocks in the BucketCache and META blocks -- INDEX and BLOOMS
* are managed by {@link org.apache.hadoop.hbase.io.hfile.CombinedBlockCache} by default. For the * -- in an instance of the LruBlockCache. For the
* CombinedBlockCache (from the class comment), "The smaller lruCache is used * CombinedBlockCache (from the class comment), "[t]he smaller lruCache is used
* to cache bloom blocks and index blocks, the larger bucketCache is used to * to cache bloom blocks and index blocks, the larger bucketCache is used to
* cache data blocks. getBlock reads first from the smaller lruCache before * cache data blocks. getBlock reads first from the smaller lruCache before
* looking for the block in the bucketCache. Metrics are the combined size and * looking for the block in the bucketCache. Metrics are the combined size and
* hits and misses of both caches." To disable CombinedBlockCache and have the BucketCache act * hits and misses of both caches." To disable CombinedBlockCache and have the BucketCache act
* as a strict L2 cache to the L1 LruBlockCache (i.e. on eviction from L1, blocks go to L2), set * as a strict L2 cache to the L1 LruBlockCache (i.e. on eviction from L1, blocks go to L2), set
* {@link org.apache.hadoop.hbase.io.hfile.CacheConfig#BUCKET_CACHE_COMBINED_KEY} to false. * {@link org.apache.hadoop.hbase.io.hfile.CacheConfig#BUCKET_CACHE_COMBINED_KEY} to false. By
* Also by default, unless you change it, * default, hbase.bucketcache.combinedcache.enabled (BUCKET_CACHE_COMBINED_KEY) is true.
* {@link org.apache.hadoop.hbase.io.hfile.CacheConfig#BUCKET_CACHE_COMBINED_PERCENTAGE_KEY} *
* defaults to <code>0.9</code> (see * <p>Back to the example of setting an onheap cache of 1G and offheap of 4G with the BlockCache
* the top of the CacheConfig in the BucketCache defaults section). This means that whatever * deploy managed by CombinedBlockCache. Setting hbase.bucketcache.ioengine and
* size you set for the bucket cache with * hbase.bucketcache.size > 0 enables CombinedBlockCache.
* {@link org.apache.hadoop.hbase.io.hfile.CacheConfig#BUCKET_CACHE_SIZE_KEY}, * In <code>hbase-env.sh</code> ensure the environment
* <code>90%</code> will be used for offheap and <code>10%</code> of the size will be used * variable <code>-XX:MaxDirectMemorySize</code> is enabled and is bigger than 4G, say 5G in size:
* by the onheap {@link org.apache.hadoop.hbase.io.hfile.LruBlockCache}. * e.g. <code>-XX:MaxDirectMemorySize=5G</code>. This setting allows the JVM use offheap memory
* <p>Back to the example of setting an onheap cache of 1G and ofheap of 4G, in * up to this upper limit. Allocate more than you need because there are other consumers of
* <code>hbase-env.sh</code> ensure the java option <code>-XX:MaxDirectMemorySize</code> is * offheap memory other than BlockCache (for example DFSClient in the RegionServer uses offheap).
* enabled and 5G in size: e.g. <code>-XX:MaxDirectMemorySize=5G</code>. Then in * In <code>hbase-site.xml</code> add the following configurations:
* <code>hbase-site.xml</code> add the following configurations:
<pre>&lt;property> <pre>&lt;property>
&lt;name>hbase.bucketcache.ioengine&lt;/name> &lt;name>hbase.bucketcache.ioengine&lt;/name>
&lt;value>offheap&lt;/value> &lt;value>offheap&lt;/value>
@ -114,7 +73,8 @@
&lt;property> &lt;property>
&lt;name>hbase.bucketcache.size&lt;/name> &lt;name>hbase.bucketcache.size&lt;/name>
&lt;value>5120&lt;/value> &lt;value>5120&lt;/value>
&lt;/property></pre>. Above we set a cache of 5G, 80% of which will be offheap (4G) and 1G onheap. &lt;/property></pre>. Above we set a cache of 5G, 80% of which will be offheap (4G) and 1G onheap
* (with DATA blocks in BucketCache and INDEX blocks in the onheap LruBlockCache).
* Restart (or rolling restart) your cluster for the configs to take effect. Check logs to ensure * Restart (or rolling restart) your cluster for the configs to take effect. Check logs to ensure
* your configurations came out as expected. * your configurations came out as expected.
* *

View File

@ -73,7 +73,6 @@ public class TestBlockCacheReporting {
public void testBucketCache() throws JsonGenerationException, JsonMappingException, IOException { public void testBucketCache() throws JsonGenerationException, JsonMappingException, IOException {
this.conf.set(CacheConfig.BUCKET_CACHE_IOENGINE_KEY, "offheap"); this.conf.set(CacheConfig.BUCKET_CACHE_IOENGINE_KEY, "offheap");
this.conf.setInt(CacheConfig.BUCKET_CACHE_SIZE_KEY, 100); this.conf.setInt(CacheConfig.BUCKET_CACHE_SIZE_KEY, 100);
this.conf.setFloat(CacheConfig.BUCKET_CACHE_COMBINED_PERCENTAGE_KEY, 0.8f);
CacheConfig cc = new CacheConfig(this.conf); CacheConfig cc = new CacheConfig(this.conf);
assertTrue(cc.getBlockCache() instanceof CombinedBlockCache); assertTrue(cc.getBlockCache() instanceof CombinedBlockCache);
logPerBlock(cc.getBlockCache()); logPerBlock(cc.getBlockCache());

View File

@ -30,6 +30,7 @@ import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.SmallTests; import org.apache.hadoop.hbase.SmallTests;
import org.apache.hadoop.hbase.io.hfile.bucket.BucketCache;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -200,12 +201,27 @@ public class TestCacheConfig {
@Test @Test
public void testBucketCacheConfig() { public void testBucketCacheConfig() {
this.conf.set(CacheConfig.BUCKET_CACHE_IOENGINE_KEY, "offheap"); this.conf.set(CacheConfig.BUCKET_CACHE_IOENGINE_KEY, "offheap");
this.conf.setInt(CacheConfig.BUCKET_CACHE_SIZE_KEY, 100); final float percent = 0.8f;
this.conf.setFloat(CacheConfig.BUCKET_CACHE_COMBINED_PERCENTAGE_KEY, 0.8f); this.conf.setFloat(CacheConfig.BUCKET_CACHE_COMBINED_PERCENTAGE_KEY, percent);
final int bcSize = 100;
this.conf.setInt(CacheConfig.BUCKET_CACHE_SIZE_KEY, bcSize);
CacheConfig cc = new CacheConfig(this.conf); CacheConfig cc = new CacheConfig(this.conf);
basicBlockCacheOps(cc, false, false); basicBlockCacheOps(cc, false, false);
assertTrue(cc.getBlockCache() instanceof CombinedBlockCache); assertTrue(cc.getBlockCache() instanceof CombinedBlockCache);
// TODO: Assert sizes allocated are right and proportions. // TODO: Assert sizes allocated are right and proportions.
CombinedBlockCache cbc = (CombinedBlockCache)cc.getBlockCache();
BlockCache [] bcs = cbc.getBlockCaches();
assertTrue(bcs[0] instanceof LruBlockCache);
LruBlockCache lbc = (LruBlockCache)bcs[0];
long expectedBCSize = (long)(bcSize * (1.0f - percent));
long actualBCSize = lbc.getMaxSize() / (1024 * 1024);
assertTrue(expectedBCSize == actualBCSize);
assertTrue(bcs[1] instanceof BucketCache);
BucketCache bc = (BucketCache)bcs[1];
// getMaxSize comes back in bytes but we specified size in MB
expectedBCSize = (long)(bcSize * percent);
actualBCSize = (long)(bc.getMaxSize() / (1024 * 1024));
assertTrue(expectedBCSize == actualBCSize);
} }
/** /**
@ -216,7 +232,6 @@ public class TestCacheConfig {
public void testCacheDataInL1() { public void testCacheDataInL1() {
this.conf.set(CacheConfig.BUCKET_CACHE_IOENGINE_KEY, "offheap"); this.conf.set(CacheConfig.BUCKET_CACHE_IOENGINE_KEY, "offheap");
this.conf.setInt(CacheConfig.BUCKET_CACHE_SIZE_KEY, 100); this.conf.setInt(CacheConfig.BUCKET_CACHE_SIZE_KEY, 100);
this.conf.setFloat(CacheConfig.BUCKET_CACHE_COMBINED_PERCENTAGE_KEY, 0.8f);
CacheConfig cc = new CacheConfig(this.conf); CacheConfig cc = new CacheConfig(this.conf);
assertTrue(cc.getBlockCache() instanceof CombinedBlockCache); assertTrue(cc.getBlockCache() instanceof CombinedBlockCache);
CombinedBlockCache cbc = (CombinedBlockCache)cc.getBlockCache(); CombinedBlockCache cbc = (CombinedBlockCache)cc.getBlockCache();

View File

@ -1945,7 +1945,7 @@ rs.close();
<title>Block Cache</title> <title>Block Cache</title>
<para>HBase provides three different BlockCache implementations: the default onheap <para>HBase provides three different BlockCache implementations: the default onheap
LruBlockCache, and BucketCache, and SlabCache, which are both (usually) offheap. This section LruBlockCache, BucketCache, and SlabCache, which are both (usually) offheap. This section
discusses benefits and drawbacks of each implementation, how to choose the appropriate discusses benefits and drawbacks of each implementation, how to choose the appropriate
option, and configuration options for each.</para> option, and configuration options for each.</para>
<section> <section>
@ -1980,10 +1980,7 @@ rs.close();
works so differently, it is difficult to do a fair comparison between BucketCache and SlabCache. works so differently, it is difficult to do a fair comparison between BucketCache and SlabCache.
See Nick Dimiduk's <link See Nick Dimiduk's <link
xlink:href="http://www.n10k.com/blog/blockcache-101/">BlockCache 101</link> for some xlink:href="http://www.n10k.com/blog/blockcache-101/">BlockCache 101</link> for some
numbers. See also the description of <link numbers.</para>
xlink:href="https://issues.apache.org/jira/browse/HBASE-7404">HBASE-7404</link> where
Chunhui Shen lists issues he found with BlockCache, such as inefficient use of memory
and garbage-collection overhead.</para>
<para>For more information about the off heap cache options, see <xref <para>For more information about the off heap cache options, see <xref
linkend="offheap.blockcache" />.</para> linkend="offheap.blockcache" />.</para>
</section> </section>
@ -2164,16 +2161,11 @@ rs.close();
</section> </section>
<section> <section>
<title>Enable BucketCache</title> <title>Enable BucketCache</title>
<para> To enable BucketCache, set the value of <para>The usual deploy of BucketCache is via a
<varname>hbase.offheapcache.percentage</varname> to 0 in the RegionServer's
<filename>hbase-site.xml</filename> file. This disables SlabCache.</para>
<para>Just as for SlabCache, the usual deploy of BucketCache is via a
managing class that sets up two caching tiers: an L1 onheap cache managing class that sets up two caching tiers: an L1 onheap cache
implemented by LruBlockCache and a second L2 cache implemented implemented by LruBlockCache and a second L2 cache implemented
with BucketCache. The managing class is <link with BucketCache. The managing class is <link
xlink:href="http://hbase.apache.org/devapidocs/org/apache/hadoop/hbase/io/hfile/CombinedBlockCache.html">CombinedBlockCache</link> xlink:href="http://hbase.apache.org/devapidocs/org/apache/hadoop/hbase/io/hfile/CombinedBlockCache.html">CombinedBlockCache</link> by default. The just-previous link describes the mechanism of CombinedBlockCache. In short, it works
by default. The just-previous link describes the mechanism of CombinedBlockCache. In short, it works
by keeping meta blocks -- INDEX and BLOOM in the L1, onheap LruBlockCache tier -- and DATA by keeping meta blocks -- INDEX and BLOOM in the L1, onheap LruBlockCache tier -- and DATA
blocks are kept in the L2, BucketCache tier. It is possible to amend this behavior in blocks are kept in the L2, BucketCache tier. It is possible to amend this behavior in
HBase since version 1.0 and ask that a column family have both its meta and DATA blocks hosted onheap in the L1 tier by HBase since version 1.0 and ask that a column family have both its meta and DATA blocks hosted onheap in the L1 tier by
@ -2189,32 +2181,29 @@ rs.close();
(Useful in particular if you have some fast i/o attached to the box such (Useful in particular if you have some fast i/o attached to the box such
as SSDs). as SSDs).
</para> </para>
<para>To disable <para>To disable CombinedBlockCache, and use the BucketCache as a strict L2 cache to the L1
CombinedBlockCache, and use the BucketCache as a strict L2 cache to the L1
LruBlockCache, set <varname>CacheConfig.BUCKET_CACHE_COMBINED_KEY</varname> to LruBlockCache, set <varname>CacheConfig.BUCKET_CACHE_COMBINED_KEY</varname> to
<literal>false</literal>. In this mode, on eviction from L1, blocks go to L2.</para> <literal>false</literal>. In this mode, on eviction from L1, blocks go to L2.</para>
<para> By default, <varname>CacheConfig.BUCKET_CACHE_COMBINED_PERCENTAGE_KEY</varname>
defaults to <literal>0.9</literal>. This means that whatever size you set for the
bucket cache with <varname>CacheConfig.BUCKET_CACHE_SIZE_KEY</varname>, 90% will be
used for offheap and 10% will be used by the onheap LruBlockCache. </para>
<para>
</para>
<procedure> <procedure>
<title>BucketCache Example Configuration</title> <title>BucketCache Example Configuration</title>
<para> This sample provides a configuration for a 4 GB offheap BucketCache with a 1 GB <para>This sample provides a configuration for a 4 GB offheap BucketCache with a 1 GB
onheap cache. Configuration is performed on the RegionServer.</para> onheap cache. Configuration is performed on the RegionServer. Setting
<varname>hbase.bucketcache.ioengine</varname> and
<varname>hbase.bucketcache.size</varname> &gt; 0 enables CombinedBlockCache.
</para>
<step> <step>
<para>First, edit the RegionServer's <filename>hbase-env.sh</filename> and set <para>First, edit the RegionServer's <filename>hbase-env.sh</filename> and set
-XX:MaxDirectMemorySize to the total size of the desired onheap plus offheap, in -XX:MaxDirectMemorySize to a value greater than the offheap size wanted, in
this case, 5 GB (but expressed as 5G).</para> this case, 4 GB (expressed as 4G). Lets set it to 5G. That'll be 4G
for our offheap cache and 1G for any other uses of offheap memory (there are
other users of offheap memory other than BlockCache; e.g. DFSClient
in RegionServer can make use of offheap memory).</para>
<programlisting>-XX:MaxDirectMemorySize=5G</programlisting> <programlisting>-XX:MaxDirectMemorySize=5G</programlisting>
</step> </step>
<step> <step>
<para>Next, add the following configuration to the RegionServer's <para>Next, add the following configuration to the RegionServer's
<filename>hbase-site.xml</filename>. This configuration uses 80% of the <filename>hbase-site.xml</filename>.</para>
-XX:MaxDirectMemorySize (4 GB) for offheap, and the remainder (1 GB) for
onheap.</para>
<programlisting> <programlisting>
<![CDATA[<property> <![CDATA[<property>
<name>hbase.bucketcache.ioengine</name> <name>hbase.bucketcache.ioengine</name>