HBASE-16650 Wrong usage of BlockCache eviction stat for heap memory tuning.


Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/1384c9a0
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/1384c9a0
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/1384c9a0

Branch: refs/heads/hbase-14439
Commit: 1384c9a08dd356556748ca0cc5853a695a40932c
Parents: 4bb84f7
Author: anoopsamjohn <anoopsamj...@gmail.com>
Authored: Thu Sep 22 21:28:30 2016 +0530
Committer: anoopsamjohn <anoopsamj...@gmail.com>
Committed: Thu Sep 22 21:28:30 2016 +0530

----------------------------------------------------------------------
 .../regionserver/MetricsRegionServerSource.java |  3 +-
 .../hadoop/hbase/io/hfile/CacheConfig.java      | 48 ++++++++++++++------
 .../hadoop/hbase/io/hfile/LruBlockCache.java    | 22 +++++----
 .../hbase/regionserver/HeapMemoryManager.java   |  8 ++--
 .../hbase/io/hfile/TestBlockCacheReporting.java |  4 +-
 .../hadoop/hbase/io/hfile/TestCacheConfig.java  |  8 ++--
 .../io/hfile/TestForceCacheImportantBlocks.java |  2 +-
 .../hfile/TestLazyDataBlockDecompression.java   |  4 +-
 .../io/hfile/TestScannerFromBucketCache.java    |  2 +-
 .../hbase/regionserver/TestStoreFile.java       |  6 +--
 10 files changed, 64 insertions(+), 43 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/1384c9a0/hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServerSource.java
----------------------------------------------------------------------
diff --git 
a/hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServerSource.java
 
b/hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServerSource.java
index a80745d..1e9b7ef 100644
--- 
a/hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServerSource.java
+++ 
b/hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/regionserver/MetricsRegionServerSource.java
@@ -285,7 +285,8 @@ public interface MetricsRegionServerSource extends 
BaseSource, JvmPauseMonitorSo
       "Number of requests for a block of primary replica that missed the block 
cache.";
   String BLOCK_CACHE_EVICTION_COUNT = "blockCacheEvictionCount";
   String BLOCK_CACHE_EVICTION_COUNT_DESC =
-      "Count of the number of blocks evicted from the block cache.";
+      "Count of the number of blocks evicted from the block cache."
+      + "(Not including blocks evicted because of HFile removal)";
   String BLOCK_CACHE_PRIMARY_EVICTION_COUNT = "blockCacheEvictionCountPrimary";
   String BLOCK_CACHE_PRIMARY_EVICTION_COUNT_DESC =
       "Count of the number of blocks evicted from primary replica in the block 
cache.";

http://git-wip-us.apache.org/repos/asf/hbase/blob/1384c9a0/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/CacheConfig.java
----------------------------------------------------------------------
diff --git 
a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/CacheConfig.java 
b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/CacheConfig.java
index ffb9424..321f72c 100644
--- 
a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/CacheConfig.java
+++ 
b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/CacheConfig.java
@@ -22,7 +22,6 @@ import static 
org.apache.hadoop.hbase.HConstants.BUCKET_CACHE_SIZE_KEY;
 
 import java.io.IOException;
 import java.lang.management.ManagementFactory;
-import java.lang.management.MemoryUsage;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -532,12 +531,13 @@ public class CacheConfig {
   // Clear this if in tests you'd make more than one block cache instance.
   @VisibleForTesting
   static BlockCache GLOBAL_BLOCK_CACHE_INSTANCE;
+  private static LruBlockCache GLOBAL_L1_CACHE_INSTANCE;
 
   /** Boolean whether we have disabled the block cache entirely. */
   @VisibleForTesting
   static boolean blockCacheDisabled = false;
 
-  static long getLruCacheSize(final Configuration conf, final MemoryUsage mu) {
+  static long getLruCacheSize(final Configuration conf, final long xmx) {
     float cachePercentage = 
conf.getFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY,
       HConstants.HFILE_BLOCK_CACHE_SIZE_DEFAULT);
     if (cachePercentage <= 0.0001f) {
@@ -550,30 +550,41 @@ public class CacheConfig {
     }
 
     // Calculate the amount of heap to give the heap.
-    return (long) (mu.getMax() * cachePercentage);
+    return (long) (xmx * cachePercentage);
   }
 
   /**
    * @param c Configuration to use.
-   * @param mu JMX Memory Bean
    * @return An L1 instance.  Currently an instance of LruBlockCache.
    */
-  private static LruBlockCache getL1(final Configuration c, final MemoryUsage 
mu) {
-    long lruCacheSize = getLruCacheSize(c, mu);
+  public static LruBlockCache getL1(final Configuration c) {
+    return getL1(c, 
ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getMax());
+  }
+
+  /**
+   * @param c Configuration to use.
+   * @param xmx Max heap memory
+   * @return An L1 instance.  Currently an instance of LruBlockCache.
+   */
+  private synchronized static LruBlockCache getL1(final Configuration c, final 
long xmx) {
+    if (GLOBAL_L1_CACHE_INSTANCE != null) return GLOBAL_L1_CACHE_INSTANCE;
+    if (blockCacheDisabled) return null;
+    long lruCacheSize = getLruCacheSize(c, xmx);
     if (lruCacheSize < 0) return null;
     int blockSize = c.getInt(BLOCKCACHE_BLOCKSIZE_KEY, 
HConstants.DEFAULT_BLOCKSIZE);
     LOG.info("Allocating LruBlockCache size=" +
       StringUtils.byteDesc(lruCacheSize) + ", blockSize=" + 
StringUtils.byteDesc(blockSize));
-    return new LruBlockCache(lruCacheSize, blockSize, true, c);
+    GLOBAL_L1_CACHE_INSTANCE = new LruBlockCache(lruCacheSize, blockSize, 
true, c);
+    return GLOBAL_L1_CACHE_INSTANCE;
   }
 
   /**
    * @param c Configuration to use.
-   * @param mu JMX Memory Bean
+   * @param xmx Max heap memory
    * @return Returns L2 block cache instance (for now it is BucketCache 
BlockCache all the time)
    * or null if not supposed to be a L2.
    */
-  private static BlockCache getL2(final Configuration c, final MemoryUsage mu) 
{
+  private static BlockCache getL2(final Configuration c, final long xmx) {
     final boolean useExternal = c.getBoolean(EXTERNAL_BLOCKCACHE_KEY, 
EXTERNAL_BLOCKCACHE_DEFAULT);
     if (LOG.isDebugEnabled()) {
       LOG.debug("Trying to use " + (useExternal?" External":" Internal") + " 
l2 cache");
@@ -585,7 +596,7 @@ public class CacheConfig {
     }
 
     // otherwise use the bucket cache.
-    return getBucketCache(c, mu);
+    return getBucketCache(c, xmx);
 
   }
 
@@ -615,14 +626,14 @@ public class CacheConfig {
 
   }
 
-  private static BlockCache getBucketCache(Configuration c, MemoryUsage mu) {
+  private static BlockCache getBucketCache(Configuration c, long xmx) {
     // Check for L2.  ioengine name must be non-null.
     String bucketCacheIOEngineName = c.get(BUCKET_CACHE_IOENGINE_KEY, null);
     if (bucketCacheIOEngineName == null || bucketCacheIOEngineName.length() <= 
0) return null;
 
     int blockSize = c.getInt(BLOCKCACHE_BLOCKSIZE_KEY, 
HConstants.DEFAULT_BLOCKSIZE);
     float bucketCachePercentage = c.getFloat(BUCKET_CACHE_SIZE_KEY, 0F);
-    long bucketCacheSize = (long) (bucketCachePercentage < 1? mu.getMax() * 
bucketCachePercentage:
+    long bucketCacheSize = (long) (bucketCachePercentage < 1? xmx * 
bucketCachePercentage:
       bucketCachePercentage * 1024 * 1024);
     if (bucketCacheSize <= 0) {
       throw new IllegalStateException("bucketCacheSize <= 0; Check " +
@@ -670,11 +681,11 @@ public class CacheConfig {
   public static synchronized BlockCache instantiateBlockCache(Configuration 
conf) {
     if (GLOBAL_BLOCK_CACHE_INSTANCE != null) return 
GLOBAL_BLOCK_CACHE_INSTANCE;
     if (blockCacheDisabled) return null;
-    MemoryUsage mu = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
-    LruBlockCache l1 = getL1(conf, mu);
+    long xmx = 
ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getMax();
+    LruBlockCache l1 = getL1(conf, xmx);
     // blockCacheDisabled is set as a side-effect of getL1(), so check it 
again after the call.
     if (blockCacheDisabled) return null;
-    BlockCache l2 = getL2(conf, mu);
+    BlockCache l2 = getL2(conf, xmx);
     if (l2 == null) {
       GLOBAL_BLOCK_CACHE_INSTANCE = l1;
     } else {
@@ -698,4 +709,11 @@ public class CacheConfig {
     }
     return GLOBAL_BLOCK_CACHE_INSTANCE;
   }
+
+  // Supposed to use only from tests. Some tests want to reinit the Global 
block cache instance
+  @VisibleForTesting
+  static synchronized void clearGlobalInstances() {
+    GLOBAL_L1_CACHE_INSTANCE = null;
+    GLOBAL_BLOCK_CACHE_INSTANCE = null;
+  }
 }

http://git-wip-us.apache.org/repos/asf/hbase/blob/1384c9a0/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/LruBlockCache.java
----------------------------------------------------------------------
diff --git 
a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/LruBlockCache.java
 
b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/LruBlockCache.java
index c56d7c6..99b67ba 100644
--- 
a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/LruBlockCache.java
+++ 
b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/LruBlockCache.java
@@ -550,15 +550,19 @@ public class LruBlockCache implements 
ResizableBlockCache, HeapSize {
       long size = map.size();
       assertCounterSanity(size, val);
     }
-    stats.evicted(block.getCachedTime(), block.getCacheKey().isPrimary());
-    if (evictedByEvictionProcess && victimHandler != null) {
-      if (victimHandler instanceof BucketCache) {
-        boolean wait = getCurrentSize() < acceptableSize();
-        boolean inMemory = block.getPriority() == BlockPriority.MEMORY;
-        ((BucketCache)victimHandler).cacheBlockWithWait(block.getCacheKey(), 
block.getBuffer(),
-            inMemory, wait);
-      } else {
-        victimHandler.cacheBlock(block.getCacheKey(), block.getBuffer());
+    if (evictedByEvictionProcess) {
+      // When the eviction of the block happened because of invalidation of 
HFiles, no need to
+      // update the stats counter.
+      stats.evicted(block.getCachedTime(), block.getCacheKey().isPrimary());
+      if (victimHandler != null) {
+        if (victimHandler instanceof BucketCache) {
+          boolean wait = getCurrentSize() < acceptableSize();
+          boolean inMemory = block.getPriority() == BlockPriority.MEMORY;
+          ((BucketCache) 
victimHandler).cacheBlockWithWait(block.getCacheKey(), block.getBuffer(),
+              inMemory, wait);
+        } else {
+          victimHandler.cacheBlock(block.getCacheKey(), block.getBuffer());
+        }
       }
     }
     return block.heapSize();

http://git-wip-us.apache.org/repos/asf/hbase/blob/1384c9a0/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemoryManager.java
----------------------------------------------------------------------
diff --git 
a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemoryManager.java
 
b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemoryManager.java
index c360a60..6226cf2 100644
--- 
a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemoryManager.java
+++ 
b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemoryManager.java
@@ -34,7 +34,6 @@ import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.ScheduledChore;
 import org.apache.hadoop.hbase.Server;
 import org.apache.hadoop.hbase.classification.InterfaceAudience;
-import org.apache.hadoop.hbase.io.hfile.BlockCache;
 import org.apache.hadoop.hbase.io.hfile.CacheConfig;
 import org.apache.hadoop.hbase.io.hfile.ResizableBlockCache;
 import org.apache.hadoop.hbase.io.util.HeapMemorySizeUtil;
@@ -93,10 +92,9 @@ public class HeapMemoryManager {
 
   public static HeapMemoryManager create(Configuration conf, FlushRequester 
memStoreFlusher,
                 Server server, RegionServerAccounting regionServerAccounting) {
-    BlockCache blockCache = CacheConfig.instantiateBlockCache(conf);
-    if (blockCache instanceof ResizableBlockCache) {
-      return new HeapMemoryManager((ResizableBlockCache) blockCache, 
memStoreFlusher, server,
-                 regionServerAccounting);
+    ResizableBlockCache l1Cache = CacheConfig.getL1(conf);
+    if (l1Cache != null) {
+      return new HeapMemoryManager(l1Cache, memStoreFlusher, server, 
regionServerAccounting);
     }
     return null;
   }

http://git-wip-us.apache.org/repos/asf/hbase/blob/1384c9a0/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestBlockCacheReporting.java
----------------------------------------------------------------------
diff --git 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestBlockCacheReporting.java
 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestBlockCacheReporting.java
index 4080249..5651c13 100644
--- 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestBlockCacheReporting.java
+++ 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestBlockCacheReporting.java
@@ -46,14 +46,14 @@ public class TestBlockCacheReporting {
 
   @Before
   public void setUp() throws Exception {
-    CacheConfig.GLOBAL_BLOCK_CACHE_INSTANCE = null;
+    CacheConfig.clearGlobalInstances();
     this.conf = HBaseConfiguration.create();
   }
 
   @After
   public void tearDown() throws Exception {
     // Let go of current block cache.
-    CacheConfig.GLOBAL_BLOCK_CACHE_INSTANCE = null;
+    CacheConfig.clearGlobalInstances();
   }
 
   private void addDataAndHits(final BlockCache bc, final int count) {

http://git-wip-us.apache.org/repos/asf/hbase/blob/1384c9a0/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.java
----------------------------------------------------------------------
diff --git 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.java
 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.java
index d8a2589..d9d5261 100644
--- 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.java
+++ 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.java
@@ -159,14 +159,14 @@ public class TestCacheConfig {
 
   @Before
   public void setUp() throws Exception {
-    CacheConfig.GLOBAL_BLOCK_CACHE_INSTANCE = null;
+    CacheConfig.clearGlobalInstances();
     this.conf = HBaseConfiguration.create();
   }
 
   @After
   public void tearDown() throws Exception {
     // Let go of current block cache.
-    CacheConfig.GLOBAL_BLOCK_CACHE_INSTANCE = null;
+    CacheConfig.clearGlobalInstances();
   }
 
   /**
@@ -329,7 +329,7 @@ public class TestCacheConfig {
     assertTrue(bcs[0] instanceof LruBlockCache);
     LruBlockCache lbc = (LruBlockCache)bcs[0];
     assertEquals(CacheConfig.getLruCacheSize(this.conf,
-        ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()), 
lbc.getMaxSize());
+        ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getMax()), 
lbc.getMaxSize());
     assertTrue(bcs[1] instanceof BucketCache);
     BucketCache bc = (BucketCache)bcs[1];
     // getMaxSize comes back in bytes but we specified size in MB
@@ -347,7 +347,7 @@ public class TestCacheConfig {
     // from L1 happens, it does not fail because L2 can't take the eviction 
because block too big.
     this.conf.setFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY, 0.001f);
     MemoryUsage mu = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
-    long lruExpectedSize = CacheConfig.getLruCacheSize(this.conf, mu);
+    long lruExpectedSize = CacheConfig.getLruCacheSize(this.conf, mu.getMax());
     final int bcSize = 100;
     long bcExpectedSize = 100 * 1024 * 1024; // MB.
     assertTrue(lruExpectedSize < bcExpectedSize);

http://git-wip-us.apache.org/repos/asf/hbase/blob/1384c9a0/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestForceCacheImportantBlocks.java
----------------------------------------------------------------------
diff --git 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestForceCacheImportantBlocks.java
 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestForceCacheImportantBlocks.java
index 4c2217d..ece658b 100644
--- 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestForceCacheImportantBlocks.java
+++ 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestForceCacheImportantBlocks.java
@@ -96,7 +96,7 @@ public class TestForceCacheImportantBlocks {
   @Before
   public void setup() {
     // Make sure we make a new one each time.
-    CacheConfig.GLOBAL_BLOCK_CACHE_INSTANCE = null;
+    CacheConfig.clearGlobalInstances();
     HFile.DATABLOCK_READ_COUNT.reset();
   }
 

http://git-wip-us.apache.org/repos/asf/hbase/blob/1384c9a0/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestLazyDataBlockDecompression.java
----------------------------------------------------------------------
diff --git 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestLazyDataBlockDecompression.java
 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestLazyDataBlockDecompression.java
index 5f73500..cf3c6ed 100644
--- 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestLazyDataBlockDecompression.java
+++ 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestLazyDataBlockDecompression.java
@@ -73,13 +73,13 @@ public class TestLazyDataBlockDecompression {
 
   @Before
   public void setUp() throws IOException {
-    CacheConfig.GLOBAL_BLOCK_CACHE_INSTANCE = null;
+    CacheConfig.clearGlobalInstances();
     fs = FileSystem.get(TEST_UTIL.getConfiguration());
   }
 
   @After
   public void tearDown() {
-    CacheConfig.GLOBAL_BLOCK_CACHE_INSTANCE = null;
+    CacheConfig.clearGlobalInstances();
     fs = null;
   }
 

http://git-wip-us.apache.org/repos/asf/hbase/blob/1384c9a0/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestScannerFromBucketCache.java
----------------------------------------------------------------------
diff --git 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestScannerFromBucketCache.java
 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestScannerFromBucketCache.java
index eb3dfa6..898f3bb 100644
--- 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestScannerFromBucketCache.java
+++ 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestScannerFromBucketCache.java
@@ -91,7 +91,7 @@ public class TestScannerFromBucketCache {
     EnvironmentEdgeManagerTestHelper.reset();
     LOG.info("Cleaning test directory: " + test_util.getDataTestDir());
     test_util.cleanupTestDir();
-    CacheConfig.GLOBAL_BLOCK_CACHE_INSTANCE = null;
+    CacheConfig.clearGlobalInstances();
   }
 
   String getName() {

http://git-wip-us.apache.org/repos/asf/hbase/blob/1384c9a0/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestStoreFile.java
----------------------------------------------------------------------
diff --git 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestStoreFile.java
 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestStoreFile.java
index f03533e..0a8dbc4 100644
--- 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestStoreFile.java
+++ 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestStoreFile.java
@@ -982,11 +982,11 @@ public class TestStoreFile extends HBaseTestCase {
     reader = hsf.createReader();
     reader.close(cacheConf.shouldEvictOnClose());
 
-    // We should have 3 new evictions
+    // We should have 3 new evictions but the evict count stat should not 
change. Eviction because
+    // of HFile invalidation is not counted along with normal evictions
     assertEquals(startHit, cs.getHitCount());
     assertEquals(startMiss, cs.getMissCount());
-    assertEquals(startEvicted + 3, cs.getEvictedCount());
-    startEvicted += 3;
+    assertEquals(startEvicted, cs.getEvictedCount());
 
     // Let's close the second file with evict on close turned off
     conf.setBoolean("hbase.rs.evictblocksonclose", false);

Reply via email to