|
17 | 17 | */ |
18 | 18 | package com.arcadedb.serializer; |
19 | 19 |
|
20 | | -import java.lang.foreign.Arena; |
21 | 20 | import java.lang.foreign.MemorySegment; |
22 | | -import java.lang.foreign.ValueLayout; |
23 | | -import java.nio.ByteOrder; |
24 | 21 |
|
25 | 22 | /** |
26 | 23 | * This class was inspired by Guava's UnsignedBytes, under Apache 2 license. |
@@ -52,79 +49,36 @@ private UnsignedBytesComparator() { |
52 | 49 | } |
53 | 50 |
|
54 | 51 | public static class ModernComparator implements ByteArrayComparator { |
55 | | - static final boolean BIG_ENDIAN = ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN); |
56 | | - |
57 | 52 | @Override |
58 | 53 | 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); |
85 | 61 | } |
86 | 62 |
|
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); |
92 | 66 | } |
93 | 67 |
|
94 | | - return left.length - right.length; |
| 68 | + return Integer.compare(Byte.toUnsignedInt(left[(int) index]), Byte.toUnsignedInt(right[(int) index])); |
95 | 69 | } |
96 | 70 |
|
97 | 71 | @Override |
98 | 72 | 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; |
119 | 76 |
|
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); |
126 | 79 |
|
127 | | - return true; |
| 80 | + // mismatch is optimized and should be faster than a for loop |
| 81 | + return leftSegment.mismatch(rightSegment) == -1; |
128 | 82 | } |
129 | 83 |
|
130 | 84 | @Override |
|
0 commit comments