There are some tricks you can do with Unsafe which are faster, but the simplest thing you can do is make sure the code is warmed up.
public static void swapIntBytes(byte[] bytes) {
assert bytes.length % 4 == 0;
for (int i = 0; i < bytes.length; i += 4) {
// swap 0 and 3
byte tmp = bytes[i];
bytes[i] = bytes[i + 3];
bytes[i + 3] = tmp;
// swap 1 and 2
byte tmp2 = bytes[i + 1];
bytes[i + 1] = bytes[i + 2];
bytes[i + 2] = tmp2;
}
}
public static void swapIntBytes2(byte[] bytes) {
assert bytes.length % 4 == 0;
IntBuffer bb1 = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN).asIntBuffer();
IntBuffer bb2 = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer();
bb1.put(bb2);
}
public static void swapIntBytes3(byte[] bytes) {
assert bytes.length % 4 == 0;
for (int i = 0; i < bytes.length; i += 4)
UNSAFE.putInt(bytes, BYTES_OFFSET + i, Integer.reverseBytes(UNSAFE.getInt(bytes, BYTES_OFFSET + i)));
}
public static void main(String... ignored) {
byte[] bytes = {1, 2, 3, 4, 5, 6, 7, 8};
swapIntBytes3(bytes);
System.out.println(Arrays.toString(bytes));
byte[] bytes4k = new byte[16384];
for (int i = 0; i < 20; i++) {
long start = System.nanoTime();
swapIntBytes(bytes4k);
long mid1 = System.nanoTime();
swapIntBytes2(bytes4k);
long mid2 = System.nanoTime();
swapIntBytes3(bytes4k);
long end = System.nanoTime();
System.out.printf("Swap byte[] %.1f us, Swap IntBuffer %.1f us, Swap UNSAFE %.1f%n",
(mid1 - start) / 1e3, (mid2 - mid1) / 1e3, (end - mid2) / 1e3);
}
}
static final Unsafe UNSAFE;
static final int BYTES_OFFSET;
static {
try {
@SuppressWarnings("ALL")
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
UNSAFE = (Unsafe) theUnsafe.get(null);
BYTES_OFFSET = UNSAFE.arrayBaseOffset(byte[].class);
} catch (Exception e) {
throw new AssertionError(e);
}
}
prints
[4, 3, 2, 1, 8, 7, 6, 5]
Swap byte[] 433.8 us, Swap IntBuffer 8577.8 us, Swap UNSAFE 1711.8
Swap byte[] 244.6 us, Swap IntBuffer 5773.1 us, Swap UNSAFE 1764.0
Swap byte[] 247.5 us, Swap IntBuffer 5059.7 us, Swap UNSAFE 1756.3
Swap byte[] 255.7 us, Swap IntBuffer 416.9 us, Swap UNSAFE 563.6
Swap byte[] 441.7 us, Swap IntBuffer 437.6 us, Swap UNSAFE 597.4
Swap byte[] 12.1 us, Swap IntBuffer 466.9 us, Swap UNSAFE 632.7
Swap byte[] 11.6 us, Swap IntBuffer 448.4 us, Swap UNSAFE 7.8
Swap byte[] 10.7 us, Swap IntBuffer 415.4 us, Swap UNSAFE 7.0
Swap byte[] 10.2 us, Swap IntBuffer 426.1 us, Swap UNSAFE 6.6
Swap byte[] 9.1 us, Swap IntBuffer 49.0 us, Swap UNSAFE 3.4
Swap byte[] 5.9 us, Swap IntBuffer 24.4 us, Swap UNSAFE 3.1
Swap byte[] 6.0 us, Swap IntBuffer 24.3 us, Swap UNSAFE 3.2
Swap byte[] 5.9 us, Swap IntBuffer 24.2 us, Swap UNSAFE 3.1
Swap byte[] 5.9 us, Swap IntBuffer 24.2 us, Swap UNSAFE 3.1
Swap byte[] 5.9 us, Swap IntBuffer 24.1 us, Swap UNSAFE 3.1
Swap byte[] 5.9 us, Swap IntBuffer 24.2 us, Swap UNSAFE 3.1
Swap byte[] 5.9 us, Swap IntBuffer 24.2 us, Swap UNSAFE 3.1
Swap byte[] 6.6 us, Swap IntBuffer 27.1 us, Swap UNSAFE 3.5
Swap byte[] 5.9 us, Swap IntBuffer 24.2 us, Swap UNSAFE 3.1
Swap byte[] 6.7 us, Swap IntBuffer 27.1 us, Swap UNSAFE 3.5