You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by la...@apache.org on 2015/09/27 01:43:59 UTC

[4/4] hbase git commit: HBASE-14489 postScannerFilterRow consumes a lot of CPU.

HBASE-14489 postScannerFilterRow consumes a lot of CPU.


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

Branch: refs/heads/branch-1.0
Commit: 8ea34aea023952df21f6ede66b63536960400ec1
Parents: 0139873
Author: Lars Hofhansl <la...@apache.org>
Authored: Sat Sep 26 16:25:17 2015 -0700
Committer: Lars Hofhansl <la...@apache.org>
Committed: Sat Sep 26 16:31:05 2015 -0700

----------------------------------------------------------------------
 .../regionserver/RegionCoprocessorHost.java     | 35 ++++++++++++++++++++
 .../hbase/coprocessor/SimpleRegionObserver.java | 12 +++++++
 .../TestRegionObserverInterface.java            | 24 ++++++++++++++
 3 files changed, 71 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/8ea34aea/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionCoprocessorHost.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionCoprocessorHost.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionCoprocessorHost.java
index afb3ec1..e20df42 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionCoprocessorHost.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RegionCoprocessorHost.java
@@ -58,6 +58,7 @@ import org.apache.hadoop.hbase.client.Mutation;
 import org.apache.hadoop.hbase.client.Put;
 import org.apache.hadoop.hbase.client.Result;
 import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.coprocessor.BaseRegionObserver;
 import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
 import org.apache.hadoop.hbase.coprocessor.CoprocessorService;
 import org.apache.hadoop.hbase.coprocessor.EndpointObserver;
@@ -100,6 +101,9 @@ public class RegionCoprocessorHost
   private static ReferenceMap sharedDataMap =
       new ReferenceMap(AbstractReferenceMap.HARD, AbstractReferenceMap.WEAK);
 
+  // optimization: no need to call postScannerFilterRow, if no coprocessor implements it
+  private final boolean hasCustomPostScannerFilterRow;
+
   /**
    * 
    * Encapsulation of the environment of each coprocessor
@@ -236,6 +240,35 @@ public class RegionCoprocessorHost
 
     // load Coprocessor From HDFS
     loadTableCoprocessors(conf);
+
+    // now check whether any coprocessor implements postScannerFilterRow
+    boolean hasCustomPostScannerFilterRow = false;
+    out: for (RegionEnvironment env: coprocessors) {
+      if (env.getInstance() instanceof RegionObserver) {
+        Class<?> clazz = env.getInstance().getClass();
+        for(;;) {
+          if (clazz == null) {
+            // we must have directly implemented RegionObserver
+            hasCustomPostScannerFilterRow = true;
+            break out;
+          }
+          if (clazz == BaseRegionObserver.class) {
+            // we reached BaseRegionObserver, try next coprocessor
+            break;
+          }
+          try {
+            clazz.getDeclaredMethod("postScannerFilterRow", ObserverContext.class,
+              InternalScanner.class, byte[].class, int.class, short.class, boolean.class);
+            // this coprocessor has a custom version of postScannerFilterRow
+            hasCustomPostScannerFilterRow = true;
+            break out;
+          } catch (NoSuchMethodException ignore) {
+          }
+          clazz = clazz.getSuperclass();
+        }
+      }
+    }
+    this.hasCustomPostScannerFilterRow = hasCustomPostScannerFilterRow;
   }
 
   static List<TableCoprocessorAttribute> getTableCoprocessorAttrsFromSchema(Configuration conf,
@@ -1371,6 +1404,8 @@ public class RegionCoprocessorHost
    */
   public boolean postScannerFilterRow(final InternalScanner s, final byte[] currentRow,
       final int offset, final short length) throws IOException {
+    // short circuit for performance
+    if (!hasCustomPostScannerFilterRow) return true;
     return execOperationWithResult(true,
         coprocessors.isEmpty() ? null : new RegionOperationWithResult<Boolean>() {
       @Override

http://git-wip-us.apache.org/repos/asf/hbase/blob/8ea34aea/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/SimpleRegionObserver.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/SimpleRegionObserver.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/SimpleRegionObserver.java
index 7100ae7..ff1dd50 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/SimpleRegionObserver.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/SimpleRegionObserver.java
@@ -118,6 +118,7 @@ public class SimpleRegionObserver extends BaseRegionObserver {
   final AtomicInteger ctPostCheckAndDelete = new AtomicInteger(0);
   final AtomicInteger ctPreScannerNext = new AtomicInteger(0);
   final AtomicInteger ctPostScannerNext = new AtomicInteger(0);
+  final AtomicInteger ctPostScannerFilterRow = new AtomicInteger(0);
   final AtomicInteger ctPreScannerClose = new AtomicInteger(0);
   final AtomicInteger ctPostScannerClose = new AtomicInteger(0);
   final AtomicInteger ctPreScannerOpen = new AtomicInteger(0);
@@ -316,6 +317,14 @@ public class SimpleRegionObserver extends BaseRegionObserver {
   }
 
   @Override
+  public boolean postScannerFilterRow(final ObserverContext<RegionCoprocessorEnvironment> e,
+      final InternalScanner s, final byte[] currentRow, final int offset, final short length,
+      final boolean hasMore) throws IOException {
+    ctPostScannerFilterRow.incrementAndGet();
+    return hasMore;
+  }
+
+  @Override
   public void preScannerClose(final ObserverContext<RegionCoprocessorEnvironment> c,
       final InternalScanner s) throws IOException {
     ctPreScannerClose.incrementAndGet();
@@ -820,6 +829,9 @@ public class SimpleRegionObserver extends BaseRegionObserver {
   public boolean wasScannerNextCalled() {
     return ctPreScannerNext.get() > 0 && ctPostScannerNext.get() > 0;
   }
+  public boolean wasScannerFilterRowCalled() {
+    return ctPostScannerFilterRow.get() > 0;
+  }
   public boolean wasScannerCloseCalled() {
     return ctPreScannerClose.get() > 0 && ctPostScannerClose.get() > 0;
   }

http://git-wip-us.apache.org/repos/asf/hbase/blob/8ea34aea/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestRegionObserverInterface.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestRegionObserverInterface.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestRegionObserverInterface.java
index 031e173..89b5049 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestRegionObserverInterface.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestRegionObserverInterface.java
@@ -59,6 +59,7 @@ import org.apache.hadoop.hbase.client.ResultScanner;
 import org.apache.hadoop.hbase.client.RowMutations;
 import org.apache.hadoop.hbase.client.Scan;
 import org.apache.hadoop.hbase.client.Table;
+import org.apache.hadoop.hbase.filter.FilterAllFilter;
 import org.apache.hadoop.hbase.io.hfile.CacheConfig;
 import org.apache.hadoop.hbase.io.hfile.HFile;
 import org.apache.hadoop.hbase.io.hfile.HFileContext;
@@ -376,6 +377,29 @@ public class TestRegionObserverInterface {
     table.close();
   }
 
+  @Test(timeout = 300000)
+  public void testHBASE14489() throws IOException {
+    TableName tableName = TableName.valueOf("testHBASE14489");
+    HTable table = util.createTable(tableName, new byte[][] { A });
+    Put put = new Put(ROW);
+    put.addColumn(A, A, A);
+    table.put(put);
+
+    Scan s = new Scan();
+    s.setFilter(new FilterAllFilter());
+    ResultScanner scanner = table.getScanner(s);
+    try {
+      for (Result rr = scanner.next(); rr != null; rr = scanner.next()) {
+      }
+    } finally {
+      scanner.close();
+    }
+    verifyMethodResult(SimpleRegionObserver.class, new String[] { "wasScannerFilterRowCalled" },
+      tableName, new Boolean[] { true });
+    util.deleteTable(tableName);
+    table.close();
+  }
+
   @Test (timeout=300000)
   // HBase-3758
   public void testHBase3758() throws IOException {