1
- /*
2
- * Copyright © 2021-present Arcade Data Ltd ([email protected] )
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 ([email protected] )
17
- * SPDX-License-Identifier: Apache-2.0
18
- */
19
1
package com .arcadedb .serializer ;
20
2
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 ;
27
5
28
6
/**
29
7
* This class was inspired by Guava's UnsignedBytes, under Apache 2 license.
35
13
*/
36
14
public final class UnsignedBytesComparator {
37
15
private static final int UNSIGNED_MASK = 0xFF ;
38
- private static final Unsafe theUnsafe ;
39
- private static final int BYTE_ARRAY_BASE_OFFSET ;
40
16
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 ();
56
18
57
19
private UnsignedBytesComparator () {
58
20
}
59
21
60
- public static class UnsafeComparator implements ByteArrayComparator {
22
+ public static class ByteBufferComparator implements ByteArrayComparator {
61
23
static final boolean BIG_ENDIAN = ByteOrder .nativeOrder ().equals (ByteOrder .BIG_ENDIAN );
62
24
63
25
@ Override
@@ -67,13 +29,12 @@ public int compare(final byte[] left, final byte[] right) {
67
29
final int strideLimit = minLength & -stride ;
68
30
int i ;
69
31
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
+
74
35
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 );
77
38
if (lw != rw ) {
78
39
if (BIG_ENDIAN ) {
79
40
return unsignedLongsCompare (lw , rw );
@@ -83,7 +44,6 @@ public int compare(final byte[] left, final byte[] right) {
83
44
}
84
45
}
85
46
86
- // The epilogue to cover the last (minLength % stride) elements.
87
47
for (; i < minLength ; i ++) {
88
48
final int result = UnsignedBytesComparator .compare (left [i ], right [i ]);
89
49
if (result != 0 )
@@ -99,18 +59,16 @@ public boolean equals(final byte[] left, final byte[] right, final int length) {
99
59
final int strideLimit = length & -stride ;
100
60
int i ;
101
61
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
+
106
65
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 );
109
68
if (lw != rw )
110
69
return false ;
111
70
}
112
71
113
- // The epilogue to cover the last (minLength % stride) elements.
114
72
for (; i < length ; i ++) {
115
73
final int result = UnsignedBytesComparator .compare (left [i ], right [i ]);
116
74
if (result != 0 )
@@ -122,7 +80,7 @@ public boolean equals(final byte[] left, final byte[] right, final int length) {
122
80
123
81
@ Override
124
82
public String toString () {
125
- return "UnsignedBytes.lexicographicalComparator() (sun.misc.Unsafe version)" ;
83
+ return "UnsignedBytes.lexicographicalComparator() (ByteBuffer version)" ;
126
84
}
127
85
}
128
86
@@ -141,7 +99,6 @@ public int compare(final byte[] left, final byte[] right) {
141
99
142
100
@ Override
143
101
public boolean equals (final byte [] left , final byte [] right , final int length ) {
144
- // OPTIMIZATION: TEST LAST BYTE FIRST
145
102
int result = UnsignedBytesComparator .compare (left [length - 1 ], right [length - 1 ]);
146
103
if (result != 0 )
147
104
return false ;
@@ -169,34 +126,4 @@ public static int unsignedLongsCompare(final long a, final long b) {
169
126
final long b2 = b ^ Long .MIN_VALUE ;
170
127
return Long .compare (a2 , b2 );
171
128
}
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
-
202
129
}
0 commit comments