From 8e08d89a50928a6757c0e8db90c6fb36e4a47eda Mon Sep 17 00:00:00 2001 From: Keith Turner Date: Tue, 8 Nov 2016 08:18:25 -0500 Subject: [PATCH] Use faster byte comparison --- .../java/org/apache/fluo/api/data/Bytes.java | 23 ++++++++++------ .../org/apache/fluo/api/data/BytesTest.java | 27 +++++++++++++++++++ 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/modules/api/src/main/java/org/apache/fluo/api/data/Bytes.java b/modules/api/src/main/java/org/apache/fluo/api/data/Bytes.java index 290277261..89b111b47 100644 --- a/modules/api/src/main/java/org/apache/fluo/api/data/Bytes.java +++ b/modules/api/src/main/java/org/apache/fluo/api/data/Bytes.java @@ -29,6 +29,7 @@ import java.util.Objects; import com.google.common.base.Preconditions; +import com.google.common.primitives.UnsignedBytes; /** * Represents bytes in Fluo. Bytes is an immutable wrapper around a byte array. Bytes always copies @@ -155,7 +156,7 @@ public InputStream toInputStream() { } public void writeTo(OutputStream out) throws IOException { - // since Bytes is immutable, its important the we do not let the internal byte array escape + // since Bytes is immutable, its important that we do not let the internal byte array escape if (length <= 32) { int end = offset + length; for (int i = offset; i < end; i++) { @@ -177,17 +178,23 @@ public void writeTo(OutputStream out) throws IOException { */ @Override public final int compareTo(Bytes other) { - int minLen = Math.min(this.length(), other.length()); + if (this == other) { + return 0; + } else if (this.length == this.data.length && other.length == other.data.length) { + return UnsignedBytes.lexicographicalComparator().compare(this.data, other.data); + } else { + int minLen = Math.min(this.length(), other.length()); - for (int i = 0; i < minLen; i++) { - int a = (this.byteAt(i) & 0xff); - int b = (other.byteAt(i) & 0xff); + for (int i = 0; i < minLen; i++) { + int a = (this.byteAt(i) & 0xff); + int b = (other.byteAt(i) & 0xff); - if (a != b) { - return a - b; + if (a != b) { + return a - b; + } } + return this.length() - other.length(); } - return this.length() - other.length(); } /** diff --git a/modules/api/src/test/java/org/apache/fluo/api/data/BytesTest.java b/modules/api/src/test/java/org/apache/fluo/api/data/BytesTest.java index 641c9bfe4..720a1a30b 100644 --- a/modules/api/src/test/java/org/apache/fluo/api/data/BytesTest.java +++ b/modules/api/src/test/java/org/apache/fluo/api/data/BytesTest.java @@ -86,9 +86,36 @@ public void testCompare() { Assert.assertEquals(-1, b1.compareTo(b2)); Assert.assertEquals(1, b2.compareTo(b1)); Assert.assertEquals(0, b1.compareTo(b3)); + Assert.assertEquals(0, b1.compareTo(b1)); Assert.assertEquals(1, b1.compareTo(Bytes.EMPTY)); } + @Test + public void testCompareSubsequence() { + Bytes b1 = Bytes.of("abcd"); + Bytes b2 = b1.subSequence(0, 3); + Bytes b3 = Bytes.of("abc"); + Bytes b4 = Bytes.of("~abcde"); + Bytes b5 = b4.subSequence(1, 4); + Bytes b6 = b4.subSequence(1, 5); + + for (Bytes ba : Arrays.asList(b2, b3, b5, b1.subSequence(0, 3))) { + for (Bytes bb : Arrays.asList(b2, b3, b5)) { + Assert.assertEquals(0, ba.compareTo(bb)); + } + } + + Assert.assertEquals(1, b1.compareTo(b2)); + Assert.assertEquals(-1, b2.compareTo(b1)); + + for (Bytes less : Arrays.asList(b2, b3, b5)) { + for (Bytes greater : Arrays.asList(b1, b4, b6)) { + Assert.assertTrue(less.compareTo(greater) < 0); + Assert.assertTrue(greater.compareTo(less) > 0); + } + } + } + @Test public void testToByteBuffer() { Bytes b1 = Bytes.of("fluofluo");