1- /*
2- * Copyright © 2021-present Arcade Data Ltd (info@arcadedata.com)
3- *
4- * Licensed under the Apache License, Version 2.0 (the "License");
5- * you may not use this file except in compliance with the License.
6- * You may obtain a copy of the License at
7- *
8- * http://www.apache.org/licenses/LICENSE-2.0
9- *
10- * Unless required by applicable law or agreed to in writing, software
11- * distributed under the License is distributed on an "AS IS" BASIS,
12- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13- * See the License for the specific language governing permissions and
14- * limitations under the License.
15- *
16- * SPDX-FileCopyrightText: 2021-present Arcade Data Ltd (info@arcadedata.com)
17- * SPDX-License-Identifier: Apache-2.0
18- */
191package com .arcadedb .serializer ;
202
21- import com .arcadedb .exception .ArcadeDBException ;
22- import sun .misc .Unsafe ;
23-
24- import java .lang .reflect .*;
25- import java .nio .*;
26- import java .security .*;
3+ import java .nio .ByteBuffer ;
4+ import java .nio .ByteOrder ;
275
286/**
297 * This class was inspired by Guava's UnsignedBytes, under Apache 2 license.
3513 */
3614public final class UnsignedBytesComparator {
3715 private static final int UNSIGNED_MASK = 0xFF ;
38- private static final Unsafe theUnsafe ;
39- private static final int BYTE_ARRAY_BASE_OFFSET ;
4016 public static final PureJavaComparator PURE_JAVA_COMPARATOR = new PureJavaComparator ();
41- public static final ByteArrayComparator BEST_COMPARATOR ;
42-
43- static {
44- theUnsafe = getUnsafe ();
45- BYTE_ARRAY_BASE_OFFSET = theUnsafe .arrayBaseOffset (byte [].class );
46- // fall back to the safer pure java implementation unless we're in
47- // a 64-bit JVM with an 8-byte aligned field offset.
48- if (!("64" .equals (System .getProperty ("sun.arch.data.model" )) && (BYTE_ARRAY_BASE_OFFSET % 8 ) == 0
49- // sanity check - this should never fail
50- && theUnsafe .arrayIndexScale (byte [].class ) == 1 )) {
51- BEST_COMPARATOR = PURE_JAVA_COMPARATOR ; // force fallback to PureJavaComparator
52- } else {
53- BEST_COMPARATOR = new UnsafeComparator ();
54- }
55- }
17+ public static final ByteArrayComparator BEST_COMPARATOR = new ByteBufferComparator ();
5618
5719 private UnsignedBytesComparator () {
5820 }
5921
60- public static class UnsafeComparator implements ByteArrayComparator {
22+ public static class ByteBufferComparator implements ByteArrayComparator {
6123 static final boolean BIG_ENDIAN = ByteOrder .nativeOrder ().equals (ByteOrder .BIG_ENDIAN );
6224
6325 @ Override
@@ -67,13 +29,12 @@ public int compare(final byte[] left, final byte[] right) {
6729 final int strideLimit = minLength & -stride ;
6830 int i ;
6931
70- /*
71- * Compare 8 bytes at a time. Benchmarking on x86 shows a stride of 8 bytes is no slower
72- * than 4 bytes even on 32-bit. On the other hand, it is substantially faster on 64-bit.
73- */
32+ ByteBuffer leftBuffer = ByteBuffer .wrap (left ).order (ByteOrder .nativeOrder ());
33+ ByteBuffer rightBuffer = ByteBuffer .wrap (right ).order (ByteOrder .nativeOrder ());
34+
7435 for (i = 0 ; i < strideLimit ; i += stride ) {
75- final long lw = theUnsafe .getLong (left , BYTE_ARRAY_BASE_OFFSET + ( long ) i );
76- final long rw = theUnsafe .getLong (right , BYTE_ARRAY_BASE_OFFSET + ( long ) i );
36+ final long lw = leftBuffer .getLong (i );
37+ final long rw = rightBuffer .getLong (i );
7738 if (lw != rw ) {
7839 if (BIG_ENDIAN ) {
7940 return unsignedLongsCompare (lw , rw );
@@ -83,7 +44,6 @@ public int compare(final byte[] left, final byte[] right) {
8344 }
8445 }
8546
86- // The epilogue to cover the last (minLength % stride) elements.
8747 for (; i < minLength ; i ++) {
8848 final int result = UnsignedBytesComparator .compare (left [i ], right [i ]);
8949 if (result != 0 )
@@ -99,18 +59,16 @@ public boolean equals(final byte[] left, final byte[] right, final int length) {
9959 final int strideLimit = length & -stride ;
10060 int i ;
10161
102- /*
103- * Compare 8 bytes at a time. Benchmarking on x86 shows a stride of 8 bytes is no slower
104- * than 4 bytes even on 32-bit. On the other hand, it is substantially faster on 64-bit.
105- */
62+ ByteBuffer leftBuffer = ByteBuffer .wrap (left ).order (ByteOrder .nativeOrder ());
63+ ByteBuffer rightBuffer = ByteBuffer .wrap (right ).order (ByteOrder .nativeOrder ());
64+
10665 for (i = 0 ; i < strideLimit ; i += stride ) {
107- final long lw = theUnsafe .getLong (left , BYTE_ARRAY_BASE_OFFSET + ( long ) i );
108- final long rw = theUnsafe .getLong (right , BYTE_ARRAY_BASE_OFFSET + ( long ) i );
66+ final long lw = leftBuffer .getLong (i );
67+ final long rw = rightBuffer .getLong (i );
10968 if (lw != rw )
11069 return false ;
11170 }
11271
113- // The epilogue to cover the last (minLength % stride) elements.
11472 for (; i < length ; i ++) {
11573 final int result = UnsignedBytesComparator .compare (left [i ], right [i ]);
11674 if (result != 0 )
@@ -122,7 +80,7 @@ public boolean equals(final byte[] left, final byte[] right, final int length) {
12280
12381 @ Override
12482 public String toString () {
125- return "UnsignedBytes.lexicographicalComparator() (sun.misc.Unsafe version)" ;
83+ return "UnsignedBytes.lexicographicalComparator() (ByteBuffer version)" ;
12684 }
12785 }
12886
@@ -141,7 +99,6 @@ public int compare(final byte[] left, final byte[] right) {
14199
142100 @ Override
143101 public boolean equals (final byte [] left , final byte [] right , final int length ) {
144- // OPTIMIZATION: TEST LAST BYTE FIRST
145102 int result = UnsignedBytesComparator .compare (left [length - 1 ], right [length - 1 ]);
146103 if (result != 0 )
147104 return false ;
@@ -169,34 +126,4 @@ public static int unsignedLongsCompare(final long a, final long b) {
169126 final long b2 = b ^ Long .MIN_VALUE ;
170127 return Long .compare (a2 , b2 );
171128 }
172-
173- /**
174- * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package. Replace with a simple
175- * call to Unsafe.getUnsafe when integrating into a jdk.
176- *
177- * @return a sun.misc.Unsafe
178- */
179- private static Unsafe getUnsafe () {
180- try {
181- return Unsafe .getUnsafe ();
182- } catch (final SecurityException e ) {
183- // that's okay; try reflection instead
184- }
185- try {
186- return AccessController .doPrivileged ((PrivilegedExceptionAction <Unsafe >) () -> {
187- final Class <Unsafe > k = Unsafe .class ;
188- for (final Field f : k .getDeclaredFields ()) {
189- f .setAccessible (true );
190- final Object x = f .get (null );
191- if (k .isInstance (x )) {
192- return k .cast (x );
193- }
194- }
195- throw new NoSuchFieldError ("the Unsafe" );
196- });
197- } catch (final PrivilegedActionException e ) {
198- throw new ArcadeDBException ("Could not initialize intrinsics" , e .getCause ());
199- }
200- }
201-
202129}
0 commit comments