You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by mb...@apache.org on 2012/10/16 14:50:47 UTC

svn commit: r1398767 - in /hbase/branches/0.89-fb/src: main/java/org/apache/hadoop/hbase/regionserver/metrics/ main/java/org/apache/hadoop/hbase/regionserver/wal/ test/java/org/apache/hadoop/hbase/regionserver/metrics/ test/java/org/apache/hadoop/hbase...

Author: mbautin
Date: Tue Oct 16 12:50:47 2012
New Revision: 1398767

URL: http://svn.apache.org/viewvc?rev=1398767&view=rev
Log:
[HBASE-6968] HBase write perf improvement II

Author: liyintang

Summary:
This diff is mainly to optimize the HLog.append function by moving some logic out of the synchronized block.

It also removed some unnecessary or unused code.

Test Plan: Will test is on the dev cluster

Reviewers: kannan

Reviewed By: kannan

CC: hbase-eng@, aaiyer

Differential Revision: https://phabricator.fb.com/D599724

Modified:
    hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/metrics/SchemaMetrics.java
    hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/wal/HLog.java
    hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/wal/WALEdit.java
    hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/regionserver/metrics/TestSchemaMetrics.java
    hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/regionserver/wal/TestHLog.java
    hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/regionserver/wal/TestLogActionsListener.java

Modified: hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/metrics/SchemaMetrics.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/metrics/SchemaMetrics.java?rev=1398767&r1=1398766&r2=1398767&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/metrics/SchemaMetrics.java (original)
+++ hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/metrics/SchemaMetrics.java Tue Oct 16 12:50:47 2012
@@ -577,15 +577,17 @@ public class SchemaMetrics {
         tableName == null || tableName.length() == 0)
       return "";
 
+    if (families.size() == 1) {
+      return SchemaMetrics.generateSchemaMetricsPrefix(tableName, 
+          Bytes.toString(families.iterator().next()));
+    }
+    
     tableName = getEffectiveTableName(tableName);
-    List<byte[]> sortedFamilies = new ArrayList<byte[]>(families);
-    Collections.sort(sortedFamilies, Bytes.BYTES_COMPARATOR);
 
     StringBuilder sb = new StringBuilder();
-
     int MAX_SIZE = 256;
     int limit = families.size();
-    for (byte[] family : sortedFamilies) {
+    for (byte[] family : families) {
       if (sb.length() > MAX_SIZE) {
         sb.append("__more");
         break;

Modified: hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/wal/HLog.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/wal/HLog.java?rev=1398767&r1=1398766&r2=1398767&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/wal/HLog.java (original)
+++ hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/wal/HLog.java Tue Oct 16 12:50:47 2012
@@ -898,22 +898,6 @@ public class HLog implements Syncable {
     }
   }
 
-   /** Append an entry to the log.
-   *
-   * @param regionInfo
-   * @param logEdit
-   * @param now Time of this edit write.
-   * @throws IOException
-   */
-  public void append(HRegionInfo regionInfo, WALEdit logEdit,
-    final long now,
-    final boolean isMetaRegion)
-  throws IOException {
-    byte [] regionName = regionInfo.getRegionName();
-    byte [] tableName = regionInfo.getTableDesc().getName();
-    this.append(regionInfo, makeKey(regionName, tableName, -1, now), logEdit);
-  }
-
   /**
    * @param now
    * @param regionName
@@ -924,44 +908,6 @@ public class HLog implements Syncable {
     return new HLogKey(regionName, tableName, seqnum, now);
   }
 
-
-
-  /** Append an entry to the log.
-   *
-   * @param regionInfo
-   * @param logEdit
-   * @param logKey
-   * @throws IOException
-   */
-  public void append(HRegionInfo regionInfo, HLogKey logKey, WALEdit logEdit)
-  throws IOException {
-    if (logSyncerThread.syncerShuttingDown) {
-      // can't acquire lock for the duration of append()
-      // so this is just a best-effort check
-      throw new IOException("Cannot append; logSyncer shutting down");
-    }
-    byte [] regionName = regionInfo.getRegionName();
-    synchronized (updateLock) {
-      if (this.closed) {
-        throw new IOException("Cannot append; log is closed");
-      }
-      long seqNum = obtainSeqNum();
-      logKey.setLogSeqNum(seqNum);
-      // The 'lastSeqWritten' map holds the sequence number of the oldest
-      // write for each region (i.e. the first edit added to the particular
-      // memstore). When the cache is flushed, the entry for the
-      // region being flushed is removed if the sequence number of the flush
-      // is greater than or equal to the value in lastSeqWritten.
-      this.lastSeqWritten.putIfAbsent(regionName, Long.valueOf(seqNum));
-      doWrite(regionInfo, logKey, logEdit);
-      this.unflushedEntries.incrementAndGet();
-      this.numEntries.incrementAndGet();
-    }
-
-    // sync txn to file system
-    this.sync(regionInfo.isMetaRegion());
-  }
-
   /**
    * Append a set of edits to the log. Log edits are keyed by regionName,
    * rowname, and log-sequence-id.
@@ -988,16 +934,21 @@ public class HLog implements Syncable {
   public void append(HRegionInfo info, byte [] tableName, WALEdit edits,
     final long now)
   throws IOException {
-    if (edits.isEmpty()) return;
-
+    if (!this.enabled || edits.isEmpty()) {
+      return;
+    }
     if (logSyncerThread.syncerShuttingDown) {
       // can't acquire lock for the duration of append()
       // so this is just a best-effort check
       throw new IOException("Cannot append; logSyncer shutting down");
     }
-    byte[] regionName = info.getRegionName();
+
+    long len = edits.getTotalKeyValueLength();
     long txid = 0;
+    
     long start = System.currentTimeMillis();
+    byte[] regionName = info.getRegionName();
+    
     synchronized (this.updateLock) {
       if (this.closed) {
         throw new IOException("Cannot append; log is closed");
@@ -1010,14 +961,24 @@ public class HLog implements Syncable {
       // is greater than or equal to the value in lastSeqWritten.
       this.lastSeqWritten.putIfAbsent(regionName, seqNum);
       HLogKey logKey = makeKey(regionName, tableName, seqNum, now);
+      
       doWrite(info, logKey, edits);
-      this.numEntries.incrementAndGet();
-
       // Only count 1 row as an unflushed entry.
       txid = this.unflushedEntries.incrementAndGet();
     }
     long time = System.currentTimeMillis() - start;
+    
+    // Update the metrics and log the outliers
+    this.numEntries.incrementAndGet();
+    writeSize.inc(len);
     writeTime.inc(time);
+    if (time > 1000) {
+      LOG.warn(String.format(
+        "%s took %d ms appending an edit to hlog; editcount=%d, len~=%s",
+        Thread.currentThread().getName(), time, this.numEntries.get(),
+        StringUtils.humanReadableInt(len)));
+    }
+    
     Call call = HRegionServer.callContext.get();
     ProfilingData pData = call == null ? null : call.getProfilingData();
     if (pData != null) {
@@ -1027,8 +988,9 @@ public class HLog implements Syncable {
     // sync txn to file system
     start = System.currentTimeMillis();
     this.sync(info.isMetaRegion(), txid);
-    long end= System.currentTimeMillis();
+    long end = System.currentTimeMillis();
     time = end - start;
+    
     gsyncTime.inc(time);
     if (pData != null) {
       if (this.lastLogRollStartTimeMillis > start
@@ -1272,29 +1234,8 @@ public class HLog implements Syncable {
 
   protected void doWrite(HRegionInfo info, HLogKey logKey, WALEdit logEdit)
   throws IOException {
-    if (!this.enabled) {
-      return;
-    }
-    if (!this.logEntryVisitors.isEmpty()) {
-      for (LogEntryVisitor visitor : this.logEntryVisitors) {
-        visitor.visitLogEntryBeforeWrite(info, logKey, logEdit);
-      }
-    }
     try {
-      long now = System.currentTimeMillis();
       this.writer.append(new HLog.Entry(logKey, logEdit));
-      long took = System.currentTimeMillis() - now;
-      long len = 0;
-      for(KeyValue kv : logEdit.getKeyValues()) {
-        len += kv.getLength();
-      }
-      writeSize.inc(len);
-      if (took > 1000) {
-        LOG.warn(String.format(
-          "%s took %d ms appending an edit to hlog; editcount=%d, len~=%s",
-          Thread.currentThread().getName(), took, this.numEntries.get(),
-          StringUtils.humanReadableInt(len)));
-      }
     } catch (IOException e) {
       LOG.fatal("Could not append. Requesting close of hlog", e);
       requestLogRoll();

Modified: hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/wal/WALEdit.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/wal/WALEdit.java?rev=1398767&r1=1398766&r2=1398767&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/wal/WALEdit.java (original)
+++ hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/wal/WALEdit.java Tue Oct 16 12:50:47 2012
@@ -73,17 +73,23 @@ public class WALEdit implements Writable
 
   private final ArrayList<KeyValue> kvs = new ArrayList<KeyValue>();
   private NavigableMap<byte[], Integer> scopes;
-
+  
+  private long length = 0;
   public WALEdit() {
   }
 
   public void add(KeyValue kv) {
     this.kvs.add(kv);
+    length += kv.getLength();
   }
 
   public boolean isEmpty() {
     return kvs.isEmpty();
   }
+  
+  public long getTotalKeyValueLength() {
+    return length;
+  }
 
   public int size() {
     return kvs.size();

Modified: hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/regionserver/metrics/TestSchemaMetrics.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/regionserver/metrics/TestSchemaMetrics.java?rev=1398767&r1=1398766&r2=1398767&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/regionserver/metrics/TestSchemaMetrics.java (original)
+++ hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/regionserver/metrics/TestSchemaMetrics.java Tue Oct 16 12:50:47 2012
@@ -29,6 +29,7 @@ import java.util.HashSet;
 import java.util.Map;
 import java.util.Random;
 import java.util.Set;
+import java.util.TreeSet;
 
 import org.apache.hadoop.hbase.HBaseTestingUtility;
 import org.apache.hadoop.hbase.io.hfile.BlockType;
@@ -234,7 +235,7 @@ public class TestSchemaMetrics {
       expected.append(".");
     }
     expected.append(SchemaMetrics.CF_PREFIX);
-    Set<byte[]> families = new HashSet<byte[]>();
+    Set<byte[]> families = new TreeSet<byte[]>(Bytes.BYTES_COMPARATOR);
     for (int i = 1; i <= numCF; i++) {
       String cf = "cf" + i;
       families.add(Bytes.toBytes(cf));

Modified: hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/regionserver/wal/TestHLog.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/regionserver/wal/TestHLog.java?rev=1398767&r1=1398766&r2=1398767&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/regionserver/wal/TestHLog.java (original)
+++ hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/regionserver/wal/TestHLog.java Tue Oct 16 12:50:47 2012
@@ -573,39 +573,7 @@ public class TestHLog  {
       }
     }
   }
-
-  /**
-   * Test that we can visit entries before they are appended
-   * @throws Exception
-   */
-  @Test
-  public void testVisitors() throws Exception {
-    final int COL_COUNT = 10;
-    final byte [] tableName = Bytes.toBytes("tablename");
-    final byte [] row = Bytes.toBytes("row");
-    HLog log = new HLog(fs, dir, oldLogDir, conf, null);
-    DumbLogEntriesVisitor visitor = new DumbLogEntriesVisitor();
-    log.addLogEntryVisitor(visitor);
-    long timestamp = System.currentTimeMillis();
-    HRegionInfo hri = new HRegionInfo(new HTableDescriptor(tableName),
-        HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW);
-    for (int i = 0; i < COL_COUNT; i++) {
-      WALEdit cols = new WALEdit();
-      cols.add(new KeyValue(row, Bytes.toBytes("column"),
-          Bytes.toBytes(Integer.toString(i)),
-          timestamp, new byte[]{(byte) (i + '0')}));
-      log.append(hri, tableName, cols, System.currentTimeMillis());
-    }
-    assertEquals(COL_COUNT, visitor.increments);
-    log.removeLogEntryVisitor(visitor);
-    WALEdit cols = new WALEdit();
-    cols.add(new KeyValue(row, Bytes.toBytes("column"),
-        Bytes.toBytes(Integer.toString(11)),
-        timestamp, new byte[]{(byte) (11 + '0')}));
-    log.append(hri, tableName, cols, System.currentTimeMillis());
-    assertEquals(COL_COUNT, visitor.increments);
-  }
-
+  
   @Test
   public void testLogCleaning() throws Exception {
     LOG.info("testLogCleaning");

Modified: hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/regionserver/wal/TestLogActionsListener.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/regionserver/wal/TestLogActionsListener.java?rev=1398767&r1=1398766&r2=1398767&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/regionserver/wal/TestLogActionsListener.java (original)
+++ hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/regionserver/wal/TestLogActionsListener.java Tue Oct 16 12:50:47 2012
@@ -93,8 +93,7 @@ public class TestLogActionsListener {
       KeyValue kv = new KeyValue(b,b,b);
       WALEdit edit = new WALEdit();
       edit.add(kv);
-      HLogKey key = new HLogKey(b,b, 0, 0);
-      hlog.append(hri, key, edit);
+      hlog.append(hri, b, edit, 0);
       if (i == 10) {
         hlog.addLogActionsListerner(laterList);
       }