Skip to content

Commit fb4c355

Browse files
committed
refactor: simplify UnsignedBytesComparator by removing unnecessary use of Arena and optimizing comparison logic
1 parent 5ea85c7 commit fb4c355

1 file changed

Lines changed: 18 additions & 64 deletions

File tree

engine/src/main/java/com/arcadedb/serializer/UnsignedBytesComparator.java

Lines changed: 18 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,7 @@
1717
*/
1818
package com.arcadedb.serializer;
1919

20-
import java.lang.foreign.Arena;
2120
import java.lang.foreign.MemorySegment;
22-
import java.lang.foreign.ValueLayout;
23-
import java.nio.ByteOrder;
2421

2522
/**
2623
* This class was inspired by Guava's UnsignedBytes, under Apache 2 license.
@@ -52,79 +49,36 @@ private UnsignedBytesComparator() {
5249
}
5350

5451
public static class ModernComparator implements ByteArrayComparator {
55-
static final boolean BIG_ENDIAN = ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN);
56-
5752
@Override
5853
public int compare(final byte[] left, final byte[] right) {
59-
final int stride = 8;
60-
final int minLength = Math.min(left.length, right.length);
61-
final int strideLimit = minLength & -stride;
62-
int i;
63-
64-
try (Arena arena = Arena.ofConfined()) {
65-
MemorySegment leftSegment = MemorySegment.ofArray(left);
66-
MemorySegment rightSegment = MemorySegment.ofArray(right);
67-
68-
/*
69-
* Compare 8 bytes at a time. Benchmarking on x86 shows a stride of 8 bytes is no slower
70-
* than 4 bytes even on 32-bit. On the other hand, it is substantially faster on 64-bit.
71-
*/
72-
for (i = 0; i < strideLimit; i += stride) {
73-
final long lw = leftSegment.get(ValueLayout.JAVA_LONG_UNALIGNED, i);
74-
final long rw = rightSegment.get(ValueLayout.JAVA_LONG_UNALIGNED, i);
75-
76-
if (lw != rw) {
77-
if (BIG_ENDIAN) {
78-
return unsignedLongsCompare(lw, rw);
79-
}
80-
81-
final int n = Long.numberOfTrailingZeros(lw ^ rw) & ~0x7;
82-
return ((int) ((lw >>> n) & UNSIGNED_MASK)) - ((int) ((rw >>> n) & UNSIGNED_MASK));
83-
}
84-
}
54+
// assumes left and right are non-null
55+
final MemorySegment leftSegment = MemorySegment.ofArray(left);
56+
final MemorySegment rightSegment = MemorySegment.ofArray(right);
57+
58+
final long index = leftSegment.mismatch(rightSegment);
59+
if (index == -1) {
60+
return Integer.compare(left.length, right.length);
8561
}
8662

87-
// The epilogue to cover the last (minLength % stride) elements.
88-
for (; i < minLength; i++) {
89-
final int result = UnsignedBytesComparator.compare(left[i], right[i]);
90-
if (result != 0)
91-
return result;
63+
// index is either the byte offset which differs or the length of the shorter array
64+
if (index >= left.length || index >= right.length) {
65+
return Integer.compare(left.length, right.length);
9266
}
9367

94-
return left.length - right.length;
68+
return Integer.compare(Byte.toUnsignedInt(left[(int) index]), Byte.toUnsignedInt(right[(int) index]));
9569
}
9670

9771
@Override
9872
public boolean equals(final byte[] left, final byte[] right, final int length) {
99-
final int stride = 8;
100-
final int strideLimit = length & -stride;
101-
int i;
102-
103-
try (Arena arena = Arena.ofConfined()) {
104-
MemorySegment leftSegment = MemorySegment.ofArray(left);
105-
MemorySegment rightSegment = MemorySegment.ofArray(right);
106-
107-
/*
108-
* Compare 8 bytes at a time. Benchmarking on x86 shows a stride of 8 bytes is no slower
109-
* than 4 bytes even on 32-bit. On the other hand, it is substantially faster on 64-bit.
110-
*/
111-
for (i = 0; i < strideLimit; i += stride) {
112-
final long lw = leftSegment.get(ValueLayout.JAVA_LONG_UNALIGNED, i);
113-
final long rw = rightSegment.get(ValueLayout.JAVA_LONG_UNALIGNED, i);
114-
115-
if (lw != rw)
116-
return false;
117-
}
118-
}
73+
// assumes left and right are non-null and length is non-zero
74+
if (left.length < length || right.length < length)
75+
return false;
11976

120-
// The epilogue to cover the last (minLength % stride) elements.
121-
for (; i < length; i++) {
122-
final int result = UnsignedBytesComparator.compare(left[i], right[i]);
123-
if (result != 0)
124-
return false;
125-
}
77+
final MemorySegment leftSegment = MemorySegment.ofArray(left).asSlice(0, length);
78+
final MemorySegment rightSegment = MemorySegment.ofArray(right).asSlice(0, length);
12679

127-
return true;
80+
// mismatch is optimized and should be faster than a for loop
81+
return leftSegment.mismatch(rightSegment) == -1;
12882
}
12983

13084
@Override

0 commit comments

Comments
 (0)