From 931089545424d8f679075054ae8d8303c70f28bd Mon Sep 17 00:00:00 2001 From: Sahil Aggarwal Date: Sat, 30 Jun 2018 10:07:30 +0530 Subject: [PATCH] HBASE-20716 Changes the bytes[] conversion is done in Bytes. Instead of doing check unsafe_aligned available everytime, choose the best converter at startup. This saves >50% in size of methods. --- .../apache/hadoop/hbase/filter/FuzzyRowFilter.java | 18 +- .../java/org/apache/hadoop/hbase/util/Bytes.java | 188 ++++++++++++++------- 2 files changed, 140 insertions(+), 66 deletions(-) diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/filter/FuzzyRowFilter.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/filter/FuzzyRowFilter.java index 714c550ddd..62d952ecdf 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/filter/FuzzyRowFilter.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/filter/FuzzyRowFilter.java @@ -351,9 +351,9 @@ public class FuzzyRowFilter extends FilterBase { int j = numWords << 3; // numWords * SIZEOF_LONG; for (int i = 0; i < j; i += Bytes.SIZEOF_LONG) { - long fuzzyBytes = UnsafeAccess.toLong(fuzzyKeyBytes, i); - long fuzzyMeta = UnsafeAccess.toLong(fuzzyKeyMeta, i); - long rowValue = UnsafeAccess.toLong(row, offset + i); + long fuzzyBytes = Bytes.toLong(fuzzyKeyBytes, i); + long fuzzyMeta = Bytes.toLong(fuzzyKeyMeta, i); + long rowValue = Bytes.toLong(row, offset + i); if ((rowValue & fuzzyMeta) != (fuzzyBytes)) { // We always return NEXT_EXISTS return SatisfiesCode.NEXT_EXISTS; @@ -363,9 +363,9 @@ public class FuzzyRowFilter extends FilterBase { int off = j; if (length - off >= Bytes.SIZEOF_INT) { - int fuzzyBytes = UnsafeAccess.toInt(fuzzyKeyBytes, off); - int fuzzyMeta = UnsafeAccess.toInt(fuzzyKeyMeta, off); - int rowValue = UnsafeAccess.toInt(row, offset + off); + int fuzzyBytes = Bytes.toInt(fuzzyKeyBytes, off); + int fuzzyMeta = Bytes.toInt(fuzzyKeyMeta, off); + int rowValue = Bytes.toInt(row, offset + off); if ((rowValue & fuzzyMeta) != (fuzzyBytes)) { // We always return NEXT_EXISTS return SatisfiesCode.NEXT_EXISTS; @@ -374,9 +374,9 @@ public class FuzzyRowFilter extends FilterBase { } if (length - off >= Bytes.SIZEOF_SHORT) { - short fuzzyBytes = UnsafeAccess.toShort(fuzzyKeyBytes, off); - short fuzzyMeta = UnsafeAccess.toShort(fuzzyKeyMeta, off); - short rowValue = UnsafeAccess.toShort(row, offset + off); + short fuzzyBytes = Bytes.toShort(fuzzyKeyBytes, off); + short fuzzyMeta = Bytes.toShort(fuzzyKeyMeta, off); + short rowValue = Bytes.toShort(row, offset + off); if ((rowValue & fuzzyMeta) != (fuzzyBytes)) { // We always return NEXT_EXISTS // even if it does not (in this case getNextForFuzzyRule diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Bytes.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Bytes.java index 15facea307..4d4bf8c3e7 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Bytes.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Bytes.java @@ -811,16 +811,7 @@ public class Bytes implements Comparable { if (length != SIZEOF_LONG || offset + length > bytes.length) { throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_LONG); } - if (UNSAFE_UNALIGNED) { - return UnsafeAccess.toLong(bytes, offset); - } else { - long l = 0; - for(int i = offset; i < offset + length; i++) { - l <<= 8; - l ^= bytes[i] & 0xFF; - } - return l; - } + return ConverterHolder.BEST_CONVERTER.toLong(bytes, offset, length); } private static IllegalArgumentException @@ -852,16 +843,7 @@ public class Bytes implements Comparable { throw new IllegalArgumentException("Not enough room to put a long at" + " offset " + offset + " in a " + bytes.length + " byte array"); } - if (UNSAFE_UNALIGNED) { - return UnsafeAccess.putLong(bytes, offset, val); - } else { - for(int i = offset + 7; i > offset; i--) { - bytes[i] = (byte) val; - val >>>= 8; - } - bytes[offset] = (byte) val; - return offset + SIZEOF_LONG; - } + return ConverterHolder.BEST_CONVERTER.putLong(bytes, offset, val); } /** @@ -1003,16 +985,7 @@ public class Bytes implements Comparable { if (length != SIZEOF_INT || offset + length > bytes.length) { throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_INT); } - if (UNSAFE_UNALIGNED) { - return UnsafeAccess.toInt(bytes, offset); - } else { - int n = 0; - for(int i = offset; i < (offset + length); i++) { - n <<= 8; - n ^= bytes[i] & 0xFF; - } - return n; - } + return ConverterHolder.BEST_CONVERTER.toInt(bytes, offset, length); } /** @@ -1087,16 +1060,7 @@ public class Bytes implements Comparable { throw new IllegalArgumentException("Not enough room to put an int at" + " offset " + offset + " in a " + bytes.length + " byte array"); } - if (UNSAFE_UNALIGNED) { - return UnsafeAccess.putInt(bytes, offset, val); - } else { - for(int i= offset + 3; i > offset; i--) { - bytes[i] = (byte) val; - val >>>= 8; - } - bytes[offset] = (byte) val; - return offset + SIZEOF_INT; - } + return ConverterHolder.BEST_CONVERTER.putInt(bytes, offset, val); } /** @@ -1157,15 +1121,7 @@ public class Bytes implements Comparable { if (length != SIZEOF_SHORT || offset + length > bytes.length) { throw explainWrongLengthOrOffset(bytes, offset, length, SIZEOF_SHORT); } - if (UNSAFE_UNALIGNED) { - return UnsafeAccess.toShort(bytes, offset); - } else { - short n = 0; - n = (short) ((n ^ bytes[offset]) & 0xFF); - n = (short) (n << 8); - n = (short) ((n ^ bytes[offset+1]) & 0xFF); - return n; - } + return ConverterHolder.BEST_CONVERTER.toShort(bytes, offset, length); } /** @@ -1195,14 +1151,7 @@ public class Bytes implements Comparable { throw new IllegalArgumentException("Not enough room to put a short at" + " offset " + offset + " in a " + bytes.length + " byte array"); } - if (UNSAFE_UNALIGNED) { - return UnsafeAccess.putShort(bytes, offset, val); - } else { - bytes[offset+1] = (byte) val; - val >>= 8; - bytes[offset] = (byte) val; - return offset + SIZEOF_SHORT; - } + return ConverterHolder.BEST_CONVERTER.putShort(bytes, offset, val); } /** @@ -1431,11 +1380,136 @@ public class Bytes implements Comparable { ); } + static abstract class Converter { + abstract long toLong(byte[] bytes, int offset, int length); + abstract int putLong(byte[] bytes, int offset, long val); + + abstract int toInt(byte[] bytes, int offset, final int length); + abstract int putInt(byte[] bytes, int offset, int val); + + abstract short toShort(byte[] bytes, int offset, final int length); + abstract int putShort(byte[] bytes, int offset, short val); + + } + @VisibleForTesting static Comparer lexicographicalComparerJavaImpl() { return LexicographicalComparerHolder.PureJavaComparer.INSTANCE; } + static class ConverterHolder { + static final Converter BEST_CONVERTER = getBestConverter(); + + static Converter getBestConverter() { + if(UNSAFE_UNALIGNED) { + return UnsafeConverter.INSTANCE; + } else { + return PureJavaConverter.INSTANCE; + } + } + + static class PureJavaConverter extends Converter { + static final PureJavaConverter INSTANCE = new PureJavaConverter(); + + private PureJavaConverter() {} + + @Override + public long toLong(byte[] bytes, int offset, int length) { + long l = 0; + for(int i = offset; i < offset + length; i++) { + l <<= 8; + l ^= bytes[i] & 0xFF; + } + return l; + } + + @Override + public int putLong(byte[] bytes, int offset, long val) { + for(int i = offset + 7; i > offset; i--) { + bytes[i] = (byte) val; + val >>>= 8; + } + bytes[offset] = (byte) val; + return offset + SIZEOF_LONG; + } + + @Override + int toInt(byte[] bytes, int offset, int length) { + int n = 0; + for(int i = offset; i < (offset + length); i++) { + n <<= 8; + n ^= bytes[i] & 0xFF; + } + return n; + } + + @Override + int putInt(byte[] bytes, int offset, int val) { + for(int i= offset + 3; i > offset; i--) { + bytes[i] = (byte) val; + val >>>= 8; + } + bytes[offset] = (byte) val; + return offset + SIZEOF_INT; + } + + @Override + short toShort(byte[] bytes, int offset, int length) { + short n = 0; + n = (short) ((n ^ bytes[offset]) & 0xFF); + n = (short) (n << 8); + n = (short) ((n ^ bytes[offset+1]) & 0xFF); + return n; + } + + @Override + int putShort(byte[] bytes, int offset, short val) { + bytes[offset+1] = (byte) val; + val >>= 8; + bytes[offset] = (byte) val; + return offset + SIZEOF_SHORT; + } + } + + static class UnsafeConverter extends Converter { + static final UnsafeConverter INSTANCE = new UnsafeConverter(); + + private UnsafeConverter() {} + + static final Unsafe theUnsafe = UnsafeAccess.theUnsafe; + + @Override + public long toLong(byte[] bytes, int offset, int length) { + return UnsafeAccess.toLong(bytes, offset); + } + + @Override + public int putLong(byte[] bytes, int offset, long val) { + return UnsafeAccess.putLong(bytes, offset, val); + } + + @Override + int toInt(byte[] bytes, int offset, int length) { + return UnsafeAccess.toInt(bytes, offset); + } + + @Override + int putInt(byte[] bytes, int offset, int val) { + return UnsafeAccess.putInt(bytes, offset, val); + } + + @Override + short toShort(byte[] bytes, int offset, int length) { + return UnsafeAccess.toShort(bytes, offset); + } + + @Override + int putShort(byte[] bytes, int offset, short val) { + return UnsafeAccess.putShort(bytes, offset, val); + } + } + } + /** * Provides a lexicographical comparer implementation; either a Java * implementation or a faster implementation based on {@link Unsafe}. -- 2.16.2