HBASE-27146 Avoid CellUtil.cloneRow in MetaCellComparator (#4571)

Signed-off-by: Bryan Beaudreault <bbeaudreault@apache.org>
Reviewed-by: SiCheng-Zheng <643463623@qq.com>
(cherry picked from commit b1691a5318)
This commit is contained in:
Duo Zhang 2022-06-24 22:29:17 +08:00
parent 2b36963d46
commit 03a1180275
3 changed files with 130 additions and 32 deletions

View File

@ -38,22 +38,46 @@ public class MetaCellComparator extends CellComparatorImpl {
*/ */
public static final MetaCellComparator META_COMPARATOR = new MetaCellComparator(); public static final MetaCellComparator META_COMPARATOR = new MetaCellComparator();
// TODO: Do we need a ByteBufferKeyValue version of this?
@Override @Override
public int compareRows(final Cell left, final Cell right) { public int compareRows(final Cell left, final Cell right) {
return compareRows(left.getRowArray(), left.getRowOffset(), left.getRowLength(), if (left instanceof ByteBufferExtendedCell) {
right.getRowArray(), right.getRowOffset(), right.getRowLength()); ByteBufferExtendedCell bbLeft = (ByteBufferExtendedCell) left;
if (right instanceof ByteBufferExtendedCell) {
ByteBufferExtendedCell bbRight = (ByteBufferExtendedCell) right;
return compareBBRows(bbLeft.getRowByteBuffer(), bbLeft.getRowPosition(),
left.getRowLength(), bbRight.getRowByteBuffer(), bbRight.getRowPosition(),
right.getRowLength());
} else {
return compareBBAndBytesRows(bbLeft.getRowByteBuffer(), bbLeft.getRowPosition(),
left.getRowLength(), right.getRowArray(), right.getRowOffset(), right.getRowLength());
}
} else {
if (right instanceof ByteBufferExtendedCell) {
ByteBufferExtendedCell bbRight = (ByteBufferExtendedCell) right;
return -compareBBAndBytesRows(bbRight.getRowByteBuffer(), bbRight.getRowPosition(),
right.getRowLength(), left.getRowArray(), left.getRowOffset(), left.getRowLength());
} else {
return compareBytesRows(left.getRowArray(), left.getRowOffset(), left.getRowLength(),
right.getRowArray(), right.getRowOffset(), right.getRowLength());
}
}
} }
@Override @Override
public int compareRows(Cell left, byte[] right, int roffset, int rlength) { public int compareRows(Cell left, byte[] right, int roffset, int rlength) {
return compareRows(left.getRowArray(), left.getRowOffset(), left.getRowLength(), right, roffset, if (left instanceof ByteBufferExtendedCell) {
rlength); ByteBufferExtendedCell bbLeft = (ByteBufferExtendedCell) left;
return compareBBAndBytesRows(bbLeft.getRowByteBuffer(), bbLeft.getRowPosition(),
left.getRowLength(), right, roffset, rlength);
} else {
return compareBytesRows(left.getRowArray(), left.getRowOffset(), left.getRowLength(), right,
roffset, rlength);
}
} }
@Override @Override
public int compareRows(byte[] leftRow, byte[] rightRow) { public int compareRows(byte[] leftRow, byte[] rightRow) {
return compareRows(leftRow, 0, leftRow.length, rightRow, 0, rightRow.length); return compareBytesRows(leftRow, 0, leftRow.length, rightRow, 0, rightRow.length);
} }
@Override @Override
@ -72,14 +96,31 @@ public class MetaCellComparator extends CellComparatorImpl {
return ignoreSequenceid ? diff : Longs.compare(b.getSequenceId(), a.getSequenceId()); return ignoreSequenceid ? diff : Longs.compare(b.getSequenceId(), a.getSequenceId());
} }
private static int compareRows(byte[] left, int loffset, int llength, byte[] right, int roffset, @FunctionalInterface
int rlength) { private interface SearchDelimiter<T> {
int leftDelimiter = Bytes.searchDelimiterIndex(left, loffset, llength, HConstants.DELIMITER); int search(T t, int offset, int length, int delimiter);
int rightDelimiter = Bytes.searchDelimiterIndex(right, roffset, rlength, HConstants.DELIMITER); }
@FunctionalInterface
private interface SearchDelimiterInReverse<T> {
int search(T t, int offset, int length, int delimiter);
}
@FunctionalInterface
private interface Compare<L, R> {
int compareTo(L left, int loffset, int llength, R right, int roffset, int rlength);
}
private static <L, R> int compareRows(L left, int loffset, int llength, R right, int roffset,
int rlength, SearchDelimiter<L> searchLeft, SearchDelimiter<R> searchRight,
SearchDelimiterInReverse<L> searchInReverseLeft,
SearchDelimiterInReverse<R> searchInReverseRight, Compare<L, R> comparator) {
int leftDelimiter = searchLeft.search(left, loffset, llength, HConstants.DELIMITER);
int rightDelimiter = searchRight.search(right, roffset, rlength, HConstants.DELIMITER);
// Compare up to the delimiter // Compare up to the delimiter
int lpart = (leftDelimiter < 0 ? llength : leftDelimiter - loffset); int lpart = (leftDelimiter < 0 ? llength : leftDelimiter - loffset);
int rpart = (rightDelimiter < 0 ? rlength : rightDelimiter - roffset); int rpart = (rightDelimiter < 0 ? rlength : rightDelimiter - roffset);
int result = Bytes.compareTo(left, loffset, lpart, right, roffset, rpart); int result = comparator.compareTo(left, loffset, lpart, right, roffset, rpart);
if (result != 0) { if (result != 0) {
return result; return result;
} else { } else {
@ -95,14 +136,14 @@ public class MetaCellComparator extends CellComparatorImpl {
// Move past delimiter // Move past delimiter
leftDelimiter++; leftDelimiter++;
rightDelimiter++; rightDelimiter++;
int leftFarDelimiter = Bytes.searchDelimiterIndexInReverse(left, leftDelimiter, int leftFarDelimiter = searchInReverseLeft.search(left, leftDelimiter,
llength - (leftDelimiter - loffset), HConstants.DELIMITER); llength - (leftDelimiter - loffset), HConstants.DELIMITER);
int rightFarDelimiter = Bytes.searchDelimiterIndexInReverse(right, rightDelimiter, int rightFarDelimiter = searchInReverseRight.search(right, rightDelimiter,
rlength - (rightDelimiter - roffset), HConstants.DELIMITER); rlength - (rightDelimiter - roffset), HConstants.DELIMITER);
// Now compare middlesection of row. // Now compare middlesection of row.
lpart = (leftFarDelimiter < 0 ? llength + loffset : leftFarDelimiter) - leftDelimiter; lpart = (leftFarDelimiter < 0 ? llength + loffset : leftFarDelimiter) - leftDelimiter;
rpart = (rightFarDelimiter < 0 ? rlength + roffset : rightFarDelimiter) - rightDelimiter; rpart = (rightFarDelimiter < 0 ? rlength + roffset : rightFarDelimiter) - rightDelimiter;
result = Bytes.compareTo(left, leftDelimiter, lpart, right, rightDelimiter, rpart); result = comparator.compareTo(left, leftDelimiter, lpart, right, rightDelimiter, rpart);
if (result != 0) { if (result != 0) {
return result; return result;
} else { } else {
@ -117,28 +158,56 @@ public class MetaCellComparator extends CellComparatorImpl {
// Compare last part of row, the rowid. // Compare last part of row, the rowid.
leftFarDelimiter++; leftFarDelimiter++;
rightFarDelimiter++; rightFarDelimiter++;
result = Bytes.compareTo(left, leftFarDelimiter, llength - (leftFarDelimiter - loffset), right, result = comparator.compareTo(left, leftFarDelimiter, llength - (leftFarDelimiter - loffset),
rightFarDelimiter, rlength - (rightFarDelimiter - roffset)); right, rightFarDelimiter, rlength - (rightFarDelimiter - roffset));
return result; return result;
} }
private static int compareBBRows(ByteBuffer left, int loffset, int llength, ByteBuffer right,
int roffset, int rlength) {
if (left.hasArray()) {
return -compareBBAndBytesRows(right, roffset, rlength, left.array(),
left.arrayOffset() + loffset, llength);
}
if (right.hasArray()) {
return compareBBAndBytesRows(left, loffset, llength, right.array(),
right.arrayOffset() + roffset, rlength);
}
return compareRows(left, loffset, llength, right, roffset, rlength,
ByteBufferUtils::searchDelimiterIndex, ByteBufferUtils::searchDelimiterIndex,
ByteBufferUtils::searchDelimiterIndexInReverse,
ByteBufferUtils::searchDelimiterIndexInReverse, ByteBufferUtils::compareTo);
}
private static int compareBBAndBytesRows(ByteBuffer left, int loffset, int llength, byte[] right,
int roffset, int rlength) {
if (left.hasArray()) {
return compareBytesRows(left.array(), left.arrayOffset() + loffset, llength, right, roffset,
rlength);
}
return compareRows(left, loffset, llength, right, roffset, rlength,
ByteBufferUtils::searchDelimiterIndex, Bytes::searchDelimiterIndex,
ByteBufferUtils::searchDelimiterIndexInReverse, Bytes::searchDelimiterIndexInReverse,
ByteBufferUtils::compareTo);
}
private static int compareBytesRows(byte[] left, int loffset, int llength, byte[] right,
int roffset, int rlength) {
return compareRows(left, loffset, llength, right, roffset, rlength, Bytes::searchDelimiterIndex,
Bytes::searchDelimiterIndex, Bytes::searchDelimiterIndexInReverse,
Bytes::searchDelimiterIndexInReverse, Bytes::compareTo);
}
@Override @Override
public int compareRows(ByteBuffer row, Cell cell) { public int compareRows(ByteBuffer row, Cell cell) {
byte[] array; if (cell instanceof ByteBufferExtendedCell) {
int offset; ByteBufferExtendedCell bbCell = (ByteBufferExtendedCell) cell;
int len = row.remaining(); return compareBBRows(row, row.position(), row.remaining(), bbCell.getRowByteBuffer(),
if (row.hasArray()) { bbCell.getRowPosition(), cell.getRowLength());
array = row.array();
offset = row.position() + row.arrayOffset();
} else { } else {
// We copy the row array if offheap just so we can do a compare. We do this elsewhere too return compareBBAndBytesRows(row, row.position(), row.remaining(), cell.getRowArray(),
// in BBUtils when Cell is backed by an offheap ByteBuffer. Needs fixing so no copy. TODO. cell.getRowOffset(), cell.getRowLength());
array = new byte[len];
offset = 0;
ByteBufferUtils.copyFromBufferToArray(array, row, row.position(), 0, len);
} }
// Reverse result since we swap the order of the params we pass below.
return -compareRows(cell, array, offset, len);
} }
@Override @Override

View File

@ -1216,4 +1216,32 @@ public final class ByteBufferUtils {
public static String toStringBinary(final ByteBuffer b) { public static String toStringBinary(final ByteBuffer b) {
return toStringBinary(b, 0, b.capacity()); return toStringBinary(b, 0, b.capacity());
} }
/**
* Find index of passed delimiter.
* @return Index of delimiter having started from start of <code>b</code> moving rightward.
*/
public static int searchDelimiterIndex(ByteBuffer b, int offset, final int length,
final int delimiter) {
for (int i = offset, n = offset + length; i < n; i++) {
if (b.get(i) == delimiter) {
return i;
}
}
return -1;
}
/**
* Find index of passed delimiter walking from end of buffer backwards.
* @return Index of delimiter
*/
public static int searchDelimiterIndexInReverse(ByteBuffer b, int offset, int length,
int delimiter) {
for (int i = offset + length - 1; i >= offset; i--) {
if (b.get(i) == delimiter) {
return i;
}
}
return -1;
}
} }

View File

@ -2576,7 +2576,8 @@ public class Bytes implements Comparable<Bytes> {
} }
/** /**
* nn * @return Index of delimiter having started from start of <code>b</code> moving rightward. * Find index of passed delimiter.
* @return Index of delimiter having started from start of <code>b</code> moving rightward.
*/ */
public static int searchDelimiterIndex(final byte[] b, int offset, final int length, public static int searchDelimiterIndex(final byte[] b, int offset, final int length,
final int delimiter) { final int delimiter) {
@ -2594,8 +2595,8 @@ public class Bytes implements Comparable<Bytes> {
} }
/** /**
* Find index of passed delimiter walking from end of buffer backwards. nn * @return Index of * Find index of passed delimiter walking from end of buffer backwards.
* delimiter * @return Index of delimiter
*/ */
public static int searchDelimiterIndexInReverse(final byte[] b, final int offset, public static int searchDelimiterIndexInReverse(final byte[] b, final int offset,
final int length, final int delimiter) { final int length, final int delimiter) {