HBASE-17877 Improve HBase's byte[] comparator.
Signed-off-by: Lars Hofhansl <larsh@apache.org>
This commit is contained in:
parent
aca4eb8d5c
commit
a2e4e0a1eb
|
@ -38,8 +38,9 @@ Copyright Jan Kovařík
|
||||||
Licensed under the Apache License v2.0 as a part of the Bootstrap project.
|
Licensed under the Apache License v2.0 as a part of the Bootstrap project.
|
||||||
|
|
||||||
--
|
--
|
||||||
This product includes portions of the Guava project v14, specifically
|
This product includes portions of the Guava project v14 and v21, specifically
|
||||||
'hbase-common/src/main/java/org/apache/hadoop/hbase/io/LimitInputStream.java'
|
'hbase-common/src/main/java/org/apache/hadoop/hbase/io/LimitInputStream.java'
|
||||||
|
'hbase-common/src/main/java/org/apache/hadoop/hbase/util/Bytes.java'
|
||||||
|
|
||||||
Copyright (C) 2007 The Guava Authors
|
Copyright (C) 2007 The Guava Authors
|
||||||
|
|
||||||
|
|
|
@ -1562,47 +1562,42 @@ public class Bytes implements Comparable<Bytes> {
|
||||||
length1 == length2) {
|
length1 == length2) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
final int stride = 8;
|
||||||
final int minLength = Math.min(length1, length2);
|
final int minLength = Math.min(length1, length2);
|
||||||
final int minWords = minLength / SIZEOF_LONG;
|
int strideLimit = minLength & ~(stride - 1);
|
||||||
final long offset1Adj = offset1 + BYTE_ARRAY_BASE_OFFSET;
|
final long offset1Adj = offset1 + BYTE_ARRAY_BASE_OFFSET;
|
||||||
final long offset2Adj = offset2 + BYTE_ARRAY_BASE_OFFSET;
|
final long offset2Adj = offset2 + BYTE_ARRAY_BASE_OFFSET;
|
||||||
|
int i;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compare 8 bytes at a time. Benchmarking shows comparing 8 bytes at a
|
* Compare 8 bytes at a time. Benchmarking on x86 shows a stride of 8 bytes is no slower
|
||||||
* time is no slower than comparing 4 bytes at a time even on 32-bit.
|
* than 4 bytes even on 32-bit. On the other hand, it is substantially faster on 64-bit.
|
||||||
* On the other hand, it is substantially faster on 64-bit.
|
|
||||||
*/
|
*/
|
||||||
// This is the end offset of long parts.
|
for (i = 0; i < strideLimit; i += stride) {
|
||||||
int j = minWords << 3; // Same as minWords * SIZEOF_LONG
|
|
||||||
for (int i = 0; i < j; i += SIZEOF_LONG) {
|
|
||||||
long lw = theUnsafe.getLong(buffer1, offset1Adj + (long) i);
|
long lw = theUnsafe.getLong(buffer1, offset1Adj + (long) i);
|
||||||
long rw = theUnsafe.getLong(buffer2, offset2Adj + (long) i);
|
long rw = theUnsafe.getLong(buffer2, offset2Adj + (long) i);
|
||||||
long diff = lw ^ rw;
|
if (lw != rw) {
|
||||||
if (diff != 0) {
|
if (!littleEndian) {
|
||||||
return lessThanUnsignedLong(lw, rw) ? -1 : 1;
|
return ((lw + Long.MIN_VALUE) < (rw + Long.MIN_VALUE)) ? -1 : 1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
int offset = j;
|
|
||||||
|
|
||||||
if (minLength - offset >= SIZEOF_INT) {
|
/*
|
||||||
int il = theUnsafe.getInt(buffer1, offset1Adj + offset);
|
* We want to compare only the first index where left[index] != right[index]. This
|
||||||
int ir = theUnsafe.getInt(buffer2, offset2Adj + offset);
|
* corresponds to the least significant nonzero byte in lw ^ rw, since lw and rw are
|
||||||
if (il != ir) {
|
* little-endian. Long.numberOfTrailingZeros(diff) tells us the least significant
|
||||||
return lessThanUnsignedInt(il, ir) ? -1: 1;
|
* nonzero bit, and zeroing out the first three bits of L.nTZ gives us the shift to get
|
||||||
|
* that least significant nonzero byte. This comparison logic is based on UnsignedBytes
|
||||||
|
* comparator from guava v21
|
||||||
|
*/
|
||||||
|
int n = Long.numberOfTrailingZeros(lw ^ rw) & ~0x7;
|
||||||
|
return ((int) ((lw >>> n) & 0xFF)) - ((int) ((rw >>> n) & 0xFF));
|
||||||
}
|
}
|
||||||
offset += SIZEOF_INT;
|
|
||||||
}
|
}
|
||||||
if (minLength - offset >= SIZEOF_SHORT) {
|
|
||||||
short sl = theUnsafe.getShort(buffer1, offset1Adj + offset);
|
// The epilogue to cover the last (minLength % stride) elements.
|
||||||
short sr = theUnsafe.getShort(buffer2, offset2Adj + offset);
|
for (; i < minLength; i++) {
|
||||||
if (sl != sr) {
|
int a = (buffer1[offset1 + i] & 0xFF);
|
||||||
return lessThanUnsignedShort(sl, sr) ? -1: 1;
|
int b = (buffer2[offset2 + i] & 0xFF);
|
||||||
}
|
|
||||||
offset += SIZEOF_SHORT;
|
|
||||||
}
|
|
||||||
if (minLength - offset == 1) {
|
|
||||||
int a = (buffer1[(int)(offset1 + offset)] & 0xff);
|
|
||||||
int b = (buffer2[(int)(offset2 + offset)] & 0xff);
|
|
||||||
if (a != b) {
|
if (a != b) {
|
||||||
return a - b;
|
return a - b;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue