You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by ns...@apache.org on 2011/10/11 04:14:34 UTC

svn commit: r1181506 - in /hbase/branches/0.89/src: main/java/org/apache/hadoop/hbase/regionserver/ test/java/org/apache/hadoop/hbase/regionserver/

Author: nspiegelberg
Date: Tue Oct 11 02:14:33 2011
New Revision: 1181506

URL: http://svn.apache.org/viewvc?rev=1181506&view=rev
Log:
put latency in prod cluster

Summary:
>From adding more metrics in the RS, we found the function reclaimMemStore takes
nearly 40% execution of multiput to get the global mem store size.

So we try to improve this by adding a new static variable in HRegion class,
which keep the record of the current global mem store size.

After changing, the reclaimMemStore takes almost 0 ms.

And we see that the multitput latency decreased dramatically.

Now this is the question, why it decreased so much?

Test Plan:
Passing unit tests.
This change may conflict when there are multiple RS running on the same
machine. It may happens in the unit test. In this case, we can change the unit
test by increasing the high water marker.

Reviewed By: kannan
Reviewers: jgray, nspiegelberg, dhruba, kannan
Commenters: dhruba, nspiegelberg
CC: nspiegelberg, dhruba, awolff, kannan
Tasks:
#503382: put latency in prod cluster

Revert Plan:
OK

Differential Revision: 227203

Modified:
    hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
    hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java
    hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreFlusher.java
    hbase/branches/0.89/src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegion.java

Modified: hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java?rev=1181506&r1=1181505&r2=1181506&view=diff
==============================================================================
--- hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java (original)
+++ hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java Tue Oct 11 02:14:33 2011
@@ -158,6 +158,7 @@ public class HRegion implements HeapSize
   // private byte [] name = null;
 
   final AtomicLong memstoreSize = new AtomicLong(0);
+  static final AtomicLong globalMemstoreSize = new AtomicLong(0);
 
   /**
    * The directory for the table this region is part of.
@@ -441,6 +442,22 @@ public class HRegion implements HeapSize
     }
   }
 
+  /**
+   * Increase the size of mem store in this region and the sum of global mem
+   * stores' size
+   * @param memStoreSize
+   * @return the size of memstore in this region
+   */
+  public long incMemoryUsage(long memStoreSize) {
+    globalMemstoreSize.addAndGet(memStoreSize);
+    return this.memstoreSize.addAndGet(memStoreSize);
+  }
+
+  /** @return the sum of global mem store size */
+  public static long getGlobalMemstoreSize() {
+    return globalMemstoreSize.get();
+  }
+
   /** @return a HRegionInfo object for this region */
   public HRegionInfo getRegionInfo() {
     return this.regionInfo;
@@ -1107,7 +1124,7 @@ public class HRegion implements HeapSize
       storeFlushers.clear();
 
       // Set down the memstore size by amount of flush.
-      this.memstoreSize.addAndGet(-currentMemStoreSize);
+      this.incMemoryUsage(-currentMemStoreSize);
     } catch (Throwable t) {
       // An exception here means that the snapshot was not persisted.
       // The hlog needs to be replayed so its content is restored to memstore.
@@ -1400,7 +1417,7 @@ public class HRegion implements HeapSize
 
       // Now make changes to the memstore.
       long addedSize = applyFamilyMapToMemstore(familyMap);
-      flush = isFlushSize(memstoreSize.addAndGet(addedSize));
+      flush = isFlushSize(this.incMemoryUsage(addedSize));
     } finally {
       this.updatesLock.readLock().unlock();
     }
@@ -1529,7 +1546,7 @@ public class HRegion implements HeapSize
       splitsAndClosesLock.readLock().lock();
       try {
         long addedSize = doMiniBatchPut(batchOp);
-        newSize = memstoreSize.addAndGet(addedSize);
+        newSize = this.incMemoryUsage(addedSize);
       } finally {
         splitsAndClosesLock.readLock().unlock();
       }
@@ -1850,7 +1867,7 @@ public class HRegion implements HeapSize
       }
 
       long addedSize = applyFamilyMapToMemstore(familyMap);
-      flush = isFlushSize(memstoreSize.addAndGet(addedSize));
+      flush = isFlushSize(this.incMemoryUsage(addedSize));
     } finally {
       this.updatesLock.readLock().unlock();
     }
@@ -2131,7 +2148,7 @@ public class HRegion implements HeapSize
    * @return True if we should flush.
    */
   protected boolean restoreEdit(final Store s, final KeyValue kv) {
-    return isFlushSize(this.memstoreSize.addAndGet(s.add(kv)));
+    return isFlushSize(this.incMemoryUsage(s.add(kv)));
   }
 
   /*
@@ -3153,7 +3170,7 @@ public class HRegion implements HeapSize
       // returns the
       long size = store.updateColumnValue(row, family, qualifier, result);
 
-      size = this.memstoreSize.addAndGet(size);
+      size = this.incMemoryUsage(size);
       flush = isFlushSize(size);
     } finally {
       this.updatesLock.readLock().unlock();

Modified: hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java?rev=1181506&r1=1181505&r2=1181506&view=diff
==============================================================================
--- hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java (original)
+++ hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java Tue Oct 11 02:14:33 2011
@@ -2293,20 +2293,6 @@ public class HRegionServer implements HR
   }
 
   /**
-   * Return the total size of all memstores in every region.
-   * @return memstore size in bytes
-   */
-  public long getGlobalMemStoreSize() {
-    long total = 0;
-    synchronized (onlineRegions) {
-      for (HRegion region : onlineRegions.values()) {
-        total += region.memstoreSize.get();
-      }
-    }
-    return total;
-  }
-
-  /**
    * @return Return the leases.
    */
   protected Leases getLeases() {

Modified: hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreFlusher.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreFlusher.java?rev=1181506&r1=1181505&r2=1181506&view=diff
==============================================================================
--- hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreFlusher.java (original)
+++ hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreFlusher.java Tue Oct 11 02:14:33 2011
@@ -287,7 +287,7 @@ class MemStoreFlusher extends Thread imp
    * amount of memstore consumption.
    */
   public synchronized void reclaimMemStoreMemory() {
-    if (server.getGlobalMemStoreSize() >= globalMemStoreLimit) {
+    if ( HRegion.getGlobalMemstoreSize() >= globalMemStoreLimit) {
       flushSomeRegions();
     }
   }
@@ -301,7 +301,7 @@ class MemStoreFlusher extends Thread imp
     ArrayList<HRegion> regionsToCompact = new ArrayList<HRegion>();
     for (SortedMap<Long, HRegion> m =
         this.server.getCopyOfOnlineRegionsSortedBySize();
-      (globalMemStoreSize = server.getGlobalMemStoreSize()) >=
+      (globalMemStoreSize = HRegion.globalMemstoreSize.get()) >=
         this.globalMemStoreLimitLowMark;) {
       // flush the region with the biggest memstore
       if (m.size() <= 0) {

Modified: hbase/branches/0.89/src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegion.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89/src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegion.java?rev=1181506&r1=1181505&r2=1181506&view=diff
==============================================================================
--- hbase/branches/0.89/src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegion.java (original)
+++ hbase/branches/0.89/src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegion.java Tue Oct 11 02:14:33 2011
@@ -201,6 +201,59 @@ public class TestHRegion extends HBaseTe
     }
   }
 
+  /**
+   * A unit test to test the global mem store size during put
+   */
+  public void testGlobalMemStoreSize() throws IOException {
+    int regionNum = 3;
+    List<HRegion> regionList = new ArrayList();
+    // create multiple regions
+    for (int r = 1; r <= regionNum; r ++) {
+      byte [] tableName = Bytes.toBytes("testGlobalMemStoreSize_r"+r);
+      byte [] fam = Bytes.toBytes("fam");
+      byte [] qf  = Bytes.toBytes("col");
+      byte [] val  = Bytes.toBytes("value");
+      // Create Table
+      HColumnDescriptor hcd = new HColumnDescriptor(fam, Integer.MAX_VALUE,
+          HColumnDescriptor.DEFAULT_COMPRESSION, false, true,
+          HColumnDescriptor.DEFAULT_TTL, "rowcol");
+
+      HTableDescriptor htd = new HTableDescriptor(tableName);
+      htd.addFamily(hcd);
+      HRegionInfo info = new HRegionInfo(htd, null, null, false);
+      Path path = new Path(DIR + "testGlobalMemStoreSize_"+r);
+      HRegion region = HRegion.createHRegion(info, path, conf);
+
+      int num_unique_rows = 10;
+      int version = 0;
+
+      for (int j = 0; j < num_unique_rows; j++) {
+        Put put = new Put(Bytes.toBytes("row" + j*r));
+        put.add(fam, qf, version++, val);
+        region.put(put);
+      }
+
+      regionList.add(region);
+    }
+
+    //cal total mem size
+    long globalMemStoreSize = 0;
+    for (HRegion region : regionList) {
+      globalMemStoreSize += region.memstoreSize.get();
+    }
+    assertTrue(HRegion.getGlobalMemstoreSize() >= globalMemStoreSize);
+
+    //cal total mem size after flush
+    globalMemStoreSize = 0;
+    for (HRegion region : regionList) {
+      region.flushcache();
+      globalMemStoreSize += region.memstoreSize.get();
+    }
+
+    assertEquals(globalMemStoreSize,0L);
+    assertTrue(HRegion.getGlobalMemstoreSize() >= globalMemStoreSize);
+  }
+
   /*
    * An involved filter test.  Has multiple column families and deletes in mix.
    */