You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by li...@apache.org on 2014/03/14 19:09:54 UTC

svn commit: r1577642 - in /hbase/branches/0.89-fb/src: main/java/org/apache/hadoop/hbase/util/Bytes.java test/java/org/apache/hadoop/hbase/util/TestBytes.java

Author: liyin
Date: Fri Mar 14 18:09:54 2014
New Revision: 1577642

URL: http://svn.apache.org/r1577642
Log:
[private] Optimize head/tail/padHead/appendToTail in Bytes, add testcases

Author: daviddeng

Summary:
Reduce the number of allocation of array when possible
Add testcases

Test Plan: `TestBytes`

Reviewers: liyintang, manukranthk, fan

Reviewed By: manukranthk

CC: hbase-eng@, andrewcox, gauravm

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

Task ID: 3839997

Modified:
    hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/util/Bytes.java
    hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/util/TestBytes.java

Modified: hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/util/Bytes.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/util/Bytes.java?rev=1577642&r1=1577641&r2=1577642&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/util/Bytes.java (original)
+++ hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/util/Bytes.java Fri Mar 14 18:09:54 2014
@@ -19,8 +19,16 @@
  */
 package org.apache.hadoop.hbase.util;
 
-import com.facebook.nifty.header.protocol.TFacebookCompactProtocol;
-import com.facebook.swift.codec.ThriftCodec;
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Iterator;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.hbase.HConstants;
@@ -33,15 +41,8 @@ import org.apache.thrift.protocol.TProto
 import org.apache.thrift.transport.TMemoryBuffer;
 import org.apache.thrift.transport.TMemoryInputTransport;
 
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.math.BigInteger;
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.Iterator;
+import com.facebook.nifty.header.protocol.TFacebookCompactProtocol;
+import com.facebook.swift.codec.ThriftCodec;
 
 /**
  * Utility class that handles byte arrays, conversions to/from other types,
@@ -1109,13 +1110,22 @@ public class Bytes {
   }
 
   /**
-   * @param a array
-   * @param length amount of bytes to grab
+   * Returns the first elements of an array.
+   *
+   * NOTE the method may return <code>a</code> if possible.
+   *
+   * @param a
+   *          a non-null array
+   * @param length
+   *          amount of bytes to grab
    * @return First <code>length</code> bytes from <code>a</code>
    */
-  public static byte [] head(final byte [] a, final int length) {
-    if (a.length < length) {
-      return null;
+  public static byte[] head(final byte[] a, final int length) {
+    if (length > a.length) {
+      throw new ArrayIndexOutOfBoundsException(length - 1);
+    }
+    if (length == a.length) {
+      return a;
     }
     byte [] result = new byte[length];
     System.arraycopy(a, 0, result, 0, length);
@@ -1123,13 +1133,22 @@ public class Bytes {
   }
 
   /**
-   * @param a array
-   * @param length amount of bytes to snarf
+   * Returns the last elements of an array.
+   *
+   * NOTE the method may return <code>a</code> if possible.
+   *
+   * @param a
+   *          a non-null array
+   * @param length
+   *          amount of bytes to snarf
    * @return Last <code>length</code> bytes from <code>a</code>
    */
-  public static byte [] tail(final byte [] a, final int length) {
-    if (a.length < length) {
-      return null;
+  public static byte[] tail(final byte[] a, final int length) {
+    if (length > a.length) {
+      throw new ArrayIndexOutOfBoundsException(a.length - length);
+    }
+    if (length == a.length) {
+      return a;
     }
     byte [] result = new byte[length];
     System.arraycopy(a, a.length - length, result, 0, length);
@@ -1137,21 +1156,35 @@ public class Bytes {
   }
 
   /**
-   * @param a array
-   * @param length new array size
-   * @return Value in <code>a</code> plus <code>length</code> prepended 0 bytes
-   */
-  public static byte [] padHead(final byte [] a, final int length) {
-    byte [] padding = new byte[length];
-    for (int i = 0; i < length; i++) {
-      padding[i] = 0;
+   * Pads zeros in front of an array.
+   *
+   * NOTE the method may return <code>a</code> if possible.
+   *
+   * @param a
+   *          a non-null array
+   * @param length
+   *          the number of zeros to be padded in
+   * @return Value in <code>a</code> plus <code>length</code> prepended 0 bytes.
+   *         could be the same instance of <code>a</code> if lenght == 0.
+   */
+  public static byte[] padHead(final byte[] a, final int length) {
+    if (length == 0) {
+      return a;
     }
-    return add(padding,a);
+    byte[] res = new byte[a.length + length];
+    System.arraycopy(a, 0, res, length, a.length);
+    return res;
   }
 
   /**
-   * @param a array
-   * @param length new array size
+   * Appends zeros at the end of <code>a</code>.
+   *
+   * NOTE the method may return <code>a</code> if possible.
+   *
+   * @param a
+   *          array
+   * @param length
+   *          new array size
    * @return Value in <code>a</code> plus <code>length</code> appended 0 bytes
    */
   public static byte [] padTail(final byte [] a, final int length) {
@@ -1161,18 +1194,31 @@ public class Bytes {
   /**
    * Appends length bytes to the end of the array and returns the new array
    * Fills byte b in the newly allocated space in the byte[].
-   * @param a array
-   * @param length new array size
-   * @param b byte to write to the tail.
+   *
+   * NOTE the method may return <code>a</code> if possible.
+   *
+   * @param a
+   *          array
+   * @param length
+   *          new array size
+   * @param b
+   *          byte to write to the tail.
    * @return Value in <code>a</code> plus <code>length</code> appended 0 bytes
    */
-  public static byte [] appendToTail(final byte [] a, final int length, byte b)
-  {
-    byte [] padding = new byte[length];
-    for (int i = 0; i < length; i++) {
-      padding[i] = b;
+  public static byte[] appendToTail(final byte[] a, int length, byte b) {
+    if (length == 0) {
+      return a;
+    }
+    int total = a.length + length;
+    byte[] res = new byte[total];
+    System.arraycopy(a, 0, res, 0, a.length);
+
+    if (b != 0) {
+      for (int i = a.length; i < total; i++) {
+        res[i] = b;
+      }
     }
-    return add(a,padding);
+    return res;
   }
 
   /**

Modified: hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/util/TestBytes.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/util/TestBytes.java?rev=1577642&r1=1577641&r2=1577642&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/util/TestBytes.java (original)
+++ hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/util/TestBytes.java Fri Mar 14 18:09:54 2014
@@ -28,6 +28,8 @@ import java.util.Arrays;
 
 import junit.framework.TestCase;
 
+import org.junit.Assert;
+
 public class TestBytes extends TestCase {
   public void testNullHashCode() {
     byte [] b = null;
@@ -170,7 +172,7 @@ public class TestBytes extends TestCase 
           Bytes.BYTES_RAWCOMPARATOR));
     }
   }
-  
+
   public void testStartsWith() {
     assertTrue(Bytes.startsWith(Bytes.toBytes("hello"), Bytes.toBytes("h")));
     assertTrue(Bytes.startsWith(Bytes.toBytes("hello"), Bytes.toBytes("")));
@@ -214,7 +216,7 @@ public class TestBytes extends TestCase 
 
     return (Bytes.toLong(testValue) + amount) == incrementResult;
   }
-  
+
   public void testFixedSizeString() throws IOException {
     ByteArrayOutputStream baos = new ByteArrayOutputStream();
     DataOutputStream dos = new DataOutputStream(baos);
@@ -240,4 +242,51 @@ public class TestBytes extends TestCase 
     assertEquals("", Bytes.readStringFixedSize(dis, 9));
   }
 
+  public void testHead() throws Exception {
+    byte[] a = new byte[] { 1, 2, 3, 4 };
+    Assert.assertArrayEquals("head(a, 0)", Bytes.head(a, 0), new byte[] {});
+    Assert.assertArrayEquals("head(a, 2)", Bytes.head(a, 2),
+        new byte[] { 1, 2 });
+    Assert.assertArrayEquals("head(a, 4)", Bytes.head(a, 4), new byte[] { 1, 2,
+        3, 4 });
+    try {
+      Bytes.head(a, 5);
+      fail("Should throw exception for head(a, 5)");
+    } catch (ArrayIndexOutOfBoundsException e) {
+      // Correct
+    }
+  }
+
+  public void testTail() throws Exception {
+    byte[] a = new byte[] { 1, 2, 3, 4 };
+    Assert.assertArrayEquals("tail(a, 0)", Bytes.tail(a, 0), new byte[] {});
+    Assert.assertArrayEquals("tail(a, 2)", Bytes.tail(a, 2),
+        new byte[] { 3, 4 });
+    Assert.assertArrayEquals("tail(a, 4)", Bytes.tail(a, 4), new byte[] { 1, 2,
+        3, 4 });
+    try {
+      Bytes.tail(a, 5);
+      fail("Should throw exception for tail(a, 5)");
+    } catch (ArrayIndexOutOfBoundsException e) {
+      // Correct
+    }
+  }
+
+  public void testPadHead() throws Exception {
+    byte[] a = new byte[] { 1, 2 };
+    Assert.assertArrayEquals("padHead(a, 0)", Bytes.padHead(a, 0), new byte[] {
+        1, 2 });
+    Assert.assertArrayEquals("padHead(a, 2)", Bytes.padHead(a, 2), new byte[] {
+        0, 0, 1, 2 });
+  }
+
+  public void testAppendToTail() throws Exception {
+    byte[] a = new byte[] { 1, 2 };
+    Assert.assertArrayEquals("appendToTail(a, 0, 0)",
+        Bytes.appendToTail(a, 0, (byte) 0), new byte[] { 1, 2 });
+    Assert.assertArrayEquals("appendToTail(a, 2, 0)",
+        Bytes.appendToTail(a, 2, (byte) 0), new byte[] { 1, 2, 0, 0 });
+    Assert.assertArrayEquals("appendToTail(a, 0, 6)",
+        Bytes.appendToTail(a, 2, (byte) 6), new byte[] { 1, 2, 6, 6 });
+  }
 }