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 2012/12/06 01:25:57 UTC

svn commit: r1417715 - in /hbase/trunk: hbase-common/src/main/java/org/apache/hadoop/hbase/ hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/ hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/

Author: larsh
Date: Thu Dec  6 00:25:56 2012
New Revision: 1417715

URL: http://svn.apache.org/viewvc?rev=1417715&view=rev
Log:
HBASE-7279 Avoid copying the rowkey in RegionScanner, StoreScanner, and ScanQueryMatcher

Modified:
    hbase/trunk/hbase-common/src/main/java/org/apache/hadoop/hbase/KeyValue.java
    hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
    hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/ScanQueryMatcher.java
    hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/StoreScanner.java
    hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestQueryMatcher.java

Modified: hbase/trunk/hbase-common/src/main/java/org/apache/hadoop/hbase/KeyValue.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-common/src/main/java/org/apache/hadoop/hbase/KeyValue.java?rev=1417715&r1=1417714&r2=1417715&view=diff
==============================================================================
--- hbase/trunk/hbase-common/src/main/java/org/apache/hadoop/hbase/KeyValue.java (original)
+++ hbase/trunk/hbase-common/src/main/java/org/apache/hadoop/hbase/KeyValue.java Thu Dec  6 00:25:56 2012
@@ -248,9 +248,6 @@ public class KeyValue implements Cell, W
   private int offset = 0;
   private int length = 0;
 
-  // the row cached
-  private volatile byte [] rowCache = null;
-
   /**
    * @return True if a delete type, a {@link KeyValue.Type#Delete} or
    * a {KeyValue.Type#DeleteFamily} or a {@link KeyValue.Type#DeleteColumn}
@@ -1240,7 +1237,6 @@ public class KeyValue implements Cell, W
       int tsOffset = getTimestampOffset();
       System.arraycopy(now, 0, this.bytes, tsOffset, Bytes.SIZEOF_LONG);
       // clear cache or else getTimestamp() possibly returns an old value
-      timestampCache = -1L;
       return true;
     }
     return false;
@@ -1312,29 +1308,20 @@ public class KeyValue implements Cell, W
    * @return Row in a new byte array.
    */
   public byte [] getRow() {
-    if (rowCache == null) {
-      int o = getRowOffset();
-      short l = getRowLength();
-      // initialize and copy the data into a local variable
-      // in case multiple threads race here.
-      byte local[] = new byte[l];
-      System.arraycopy(getBuffer(), o, local, 0, l);
-      rowCache = local; // volatile assign
-    }
-    return rowCache;
+    int o = getRowOffset();
+    short l = getRowLength();
+    byte result[] = new byte[l];
+    System.arraycopy(getBuffer(), o, result, 0, l);
+    return result;
   }
 
   /**
    *
    * @return Timestamp
    */
-  private long timestampCache = -1;
   @Override
   public long getTimestamp() {
-    if (timestampCache == -1) {
-      timestampCache = getTimestamp(getKeyLength());
-    }
-    return timestampCache;
+    return getTimestamp(getKeyLength());
   }
 
   /**
@@ -2639,12 +2626,11 @@ public class KeyValue implements Cell, W
   public long heapSize() {
     int sum = 0;
     sum += ClassSize.OBJECT;// the KeyValue object itself
-    sum += 2 * ClassSize.REFERENCE;// 2 * pointers to "bytes" and "rowCache" byte[]
-    sum += 2 * ClassSize.align(ClassSize.ARRAY);// 2 * "bytes" and "rowCache" byte[]
+    sum += ClassSize.REFERENCE;// pointer to "bytes"
+    sum += ClassSize.align(ClassSize.ARRAY);// "bytes"
     sum += ClassSize.align(length);// number of bytes of data in the "bytes" array
-    //ignore the data in the rowCache because it is cleared for inactive memstore KeyValues
     sum += 3 * Bytes.SIZEOF_INT;// offset, length, keyLength
-    sum += 2 * Bytes.SIZEOF_LONG;// timestampCache, memstoreTS
+    sum += Bytes.SIZEOF_LONG;// memstoreTS
     return ClassSize.align(sum);
   }
 
@@ -2652,10 +2638,8 @@ public class KeyValue implements Cell, W
   // and it expects the length of the KeyValue to be explicitly passed
   // to it.
   public void readFields(int length, final DataInput in) throws IOException {
-    this.rowCache = null;
     this.length = length;
     this.offset = 0;
-    this.timestampCache = -1;
     this.keyLength = 0;
     this.bytes = new byte[this.length];
     in.readFully(this.bytes, 0, this.length);

Modified: hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java?rev=1417715&r1=1417714&r2=1417715&view=diff
==============================================================================
--- hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java (original)
+++ hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java Thu Dec  6 00:25:56 2012
@@ -3536,17 +3536,25 @@ public class HRegion implements HeapSize
           rpcCall.throwExceptionIfCallerDisconnected();
         }
 
-        byte [] currentRow = peekRow();
-        if (isStopRow(currentRow)) {
+        KeyValue current = this.storeHeap.peek();
+        byte[] currentRow = null;
+        int offset = 0;
+        short length = 0;
+        if (current != null) {
+          currentRow = current.getBuffer();
+          offset = current.getRowOffset();
+          length = current.getRowLength();
+        }
+        if (isStopRow(currentRow, offset, length)) {
           if (filter != null && filter.hasFilterRow()) {
             filter.filterRow(results);
           }
           
           return false;
-        } else if (filterRowKey(currentRow)) {
-          nextRow(currentRow);
+        } else if (filterRowKey(currentRow, offset, length)) {
+          nextRow(currentRow, offset, length);
         } else {
-          byte [] nextRow;
+          KeyValue nextKv;
           do {
             this.storeHeap.next(results, limit - results.size(), metric);
             if (limit > 0 && results.size() == limit) {
@@ -3556,9 +3564,10 @@ public class HRegion implements HeapSize
               }
               return true; // we are expecting more yes, but also limited to how many we can return.
             }
-          } while (Bytes.equals(currentRow, nextRow = peekRow()));
+            nextKv = this.storeHeap.peek();
+          } while (nextKv != null && nextKv.matchingRow(currentRow, offset, length));
 
-          final boolean stopRow = isStopRow(nextRow);
+          final boolean stopRow = nextKv == null || isStopRow(nextKv.getBuffer(), nextKv.getRowOffset(), nextKv.getRowLength());
 
           // now that we have an entire row, lets process with a filters:
 
@@ -3573,7 +3582,7 @@ public class HRegion implements HeapSize
             // the reasons for calling this method are:
             // 1. reset the filters.
             // 2. provide a hook to fast forward the row (used by subclasses)
-            nextRow(currentRow);
+            nextRow(currentRow, offset, length);
 
             // This row was totally filtered out, if this is NOT the last row,
             // we should continue on.
@@ -3585,33 +3594,25 @@ public class HRegion implements HeapSize
       }
     }
 
-    private boolean filterRow() {
-      return filter != null
-          && filter.filterRow();
-    }
-    private boolean filterRowKey(byte[] row) {
+    private boolean filterRowKey(byte[] row, int offset, short length) {
       return filter != null
-          && filter.filterRowKey(row, 0, row.length);
+          && filter.filterRowKey(row, offset, length);
     }
 
-    protected void nextRow(byte [] currentRow) throws IOException {
-      while (Bytes.equals(currentRow, peekRow())) {
-        this.storeHeap.next(MOCKED_LIST);
+    protected void nextRow(byte [] currentRow, int offset, short length) throws IOException {
+      KeyValue next;
+      while((next = this.storeHeap.peek()) != null && next.matchingRow(currentRow, offset, length)) {
+        this.storeHeap.next(MOCKED_LIST);       
       }
       results.clear();
       resetFilters();
     }
 
-    private byte[] peekRow() {
-      KeyValue kv = this.storeHeap.peek();
-      return kv == null ? null : kv.getRow();
-    }
-
-    private boolean isStopRow(byte [] currentRow) {
+    private boolean isStopRow(byte [] currentRow, int offset, short length) {
       return currentRow == null ||
           (stopRow != null &&
           comparator.compareRows(stopRow, 0, stopRow.length,
-              currentRow, 0, currentRow.length) <= isScan);
+              currentRow, offset, length) <= isScan);
     }
 
     @Override

Modified: hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/ScanQueryMatcher.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/ScanQueryMatcher.java?rev=1417715&r1=1417714&r2=1417715&view=diff
==============================================================================
--- hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/ScanQueryMatcher.java (original)
+++ hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/ScanQueryMatcher.java Thu Dec  6 00:25:56 2012
@@ -83,6 +83,8 @@ public class ScanQueryMatcher {
   /* row is not private for tests */
   /** Row the query is on */
   byte [] row;
+  int rowOffset;
+  short rowLength;
   
   /**
    * Oldest put in any of the involved store files
@@ -223,7 +225,7 @@ public class ScanQueryMatcher {
     short rowLength = Bytes.toShort(bytes, offset, Bytes.SIZEOF_SHORT);
     offset += Bytes.SIZEOF_SHORT;
 
-    int ret = this.rowComparator.compareRows(row, 0, row.length,
+    int ret = this.rowComparator.compareRows(row, this.rowOffset, this.rowLength,
         bytes, offset, rowLength);
     if (ret <= -1) {
       return MatchCode.DONE;
@@ -386,8 +388,10 @@ public class ScanQueryMatcher {
    * Set current row
    * @param row
    */
-  public void setRow(byte [] row) {
+  public void setRow(byte [] row, int offset, short length) {
     this.row = row;
+    this.rowOffset = offset;
+    this.rowLength = length;
     reset();
   }
 

Modified: hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/StoreScanner.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/StoreScanner.java?rev=1417715&r1=1417714&r2=1417715&view=diff
==============================================================================
--- hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/StoreScanner.java (original)
+++ hbase/trunk/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/StoreScanner.java Thu Dec  6 00:25:56 2012
@@ -53,7 +53,6 @@ public class StoreScanner extends NonLaz
   private int storeLimit = -1;
   private int storeOffset = 0;
 
-  private String metricNamePrefix;
   // Used to indicate that the scanner has closed (see HBASE-1107)
   // Doesnt need to be volatile because it's always accessed via synchronized methods
   private boolean closing = false;
@@ -328,9 +327,12 @@ public class StoreScanner extends NonLaz
 
     // only call setRow if the row changes; avoids confusing the query matcher
     // if scanning intra-row
-    if ((matcher.row == null) || !peeked.matchingRow(matcher.row)) {
+    byte[] row = peeked.getBuffer();
+    int offset = peeked.getRowOffset();
+    short length = peeked.getRowLength();
+    if ((matcher.row == null) || !Bytes.equals(row, offset, length, matcher.row, matcher.rowOffset, matcher.rowLength)) {
       this.countPerRow = 0;
-      matcher.setRow(peeked.getRow());
+      matcher.setRow(row, offset, length);
     }
 
     KeyValue kv;
@@ -529,10 +531,13 @@ public class StoreScanner extends NonLaz
     if (kv == null) {
       kv = lastTopKey;
     }
-    if ((matcher.row == null) || !kv.matchingRow(matcher.row)) {
+    byte[] row = kv.getBuffer();
+    int offset = kv.getRowOffset();
+    short length = kv.getRowLength();
+    if ((matcher.row == null) || !Bytes.equals(row, offset, length, matcher.row, matcher.rowOffset, matcher.rowLength)) {
       this.countPerRow = 0;
       matcher.reset();
-      matcher.setRow(kv.getRow());
+      matcher.setRow(row, offset, length);
     }
   }
 

Modified: hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestQueryMatcher.java
URL: http://svn.apache.org/viewvc/hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestQueryMatcher.java?rev=1417715&r1=1417714&r2=1417715&view=diff
==============================================================================
--- hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestQueryMatcher.java (original)
+++ hbase/trunk/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestQueryMatcher.java Thu Dec  6 00:25:56 2012
@@ -112,7 +112,8 @@ public class TestQueryMatcher extends HB
     memstore.add(new KeyValue(row2, fam1, col1, data));
 
     List<ScanQueryMatcher.MatchCode> actual = new ArrayList<ScanQueryMatcher.MatchCode>();
-    qm.setRow(memstore.get(0).getRow());
+    KeyValue k = memstore.get(0);
+    qm.setRow(k.getBuffer(), k.getRowOffset(), k.getRowLength());
 
     for (KeyValue kv : memstore){
       actual.add(qm.match(kv));
@@ -157,7 +158,8 @@ public class TestQueryMatcher extends HB
 
     List<ScanQueryMatcher.MatchCode> actual = new ArrayList<ScanQueryMatcher.MatchCode>();
 
-    qm.setRow(memstore.get(0).getRow());
+    KeyValue k = memstore.get(0);
+    qm.setRow(k.getBuffer(), k.getRowOffset(), k.getRowLength());
 
     for(KeyValue kv : memstore) {
       actual.add(qm.match(kv));
@@ -209,7 +211,8 @@ public class TestQueryMatcher extends HB
         new KeyValue(row2, fam1, col1, now-10, data)
     };
 
-    qm.setRow(kvs[0].getRow());
+    KeyValue k = kvs[0];
+    qm.setRow(k.getBuffer(), k.getRowOffset(), k.getRowLength());
 
     List<MatchCode> actual = new ArrayList<MatchCode>(kvs.length);
     for (KeyValue kv : kvs) {
@@ -261,7 +264,8 @@ public class TestQueryMatcher extends HB
         new KeyValue(row1, fam2, col5, now-10000, data),
         new KeyValue(row2, fam1, col1, now-10, data)
     };
-    qm.setRow(kvs[0].getRow());
+    KeyValue k = kvs[0];
+    qm.setRow(k.getBuffer(), k.getRowOffset(), k.getRowLength());
 
     List<ScanQueryMatcher.MatchCode> actual =
         new ArrayList<ScanQueryMatcher.MatchCode>(kvs.length);