Skip to content

Instantly share code, notes, and snippets.

@vladimirdolzhenko
Created February 21, 2016 10:18
Show Gist options
  • Save vladimirdolzhenko/e69bf3a7c44eb6660163 to your computer and use it in GitHub Desktop.
Save vladimirdolzhenko/e69bf3a7c44eb6660163 to your computer and use it in GitHub Desktop.
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
import java.util.concurrent.TimeUnit;
/**
* @author vladimir.dolzhenko
* @since 2016-02-05
*/
@Fork(2)
@Warmup(iterations = 5, time = 1000, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@BenchmarkMode(Mode.AverageTime)
@Threads(1)
@State(Scope.Benchmark)
public class StringPerfTest {
static final int maxSize = 2 << 10;
public static Unsafe fetchInstance() {
try {
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
return (Unsafe) theUnsafe.get(null);
} catch (Throwable e){
throw new RuntimeException(e);
}
}
@State( Scope.Thread )
public static class ThreadState {
private Unsafe unsafe;
final long memory2k;
final byte[] bytes4 = new byte[4];
final byte[] bytes8 = new byte[8];
final byte[] bytes16 = new byte[16];
final byte[] bytes24 = new byte[24];
final byte[] bytes64 = new byte[64];
public ThreadState() {
this.unsafe = fetchInstance();
memory2k = unsafe.allocateMemory(maxSize);
}
}
@State(Scope.Benchmark)
public static class BenchmarkState {
private final int byteArrayOffset;
private Unsafe unsafe;
private final long memory2k;
public BenchmarkState() {
unsafe = fetchInstance();
memory2k = unsafe.allocateMemory(maxSize);
byteArrayOffset = unsafe.arrayBaseOffset(byte[].class);
byte[] bytes = ("some simple string with digits 123456789@@@@@!__ASDZXCXZ" +
"some simple string with digits 123456789@@@@@!__ASDZXCXZ").getBytes();
unsafe.copyMemory( bytes, byteArrayOffset, null, memory2k, bytes.length );
}
public long readInt(int offset){
return unsafe.getInt( memory2k + offset);
}
public long readLong(int offset){
return unsafe.getLong( memory2k + offset);
}
public void copy(long memory, int srcOffset, byte[] bytes, int size){
unsafe.copyMemory(null, memory + srcOffset, bytes, byteArrayOffset, size);
}
}
@Benchmark
public void string1IntsCopyMemory(BenchmarkState state, ThreadState threadState, Blackhole bh){
final int length = 4;
state.copy(state.memory2k, 0, threadState.bytes4, length);
bh.consume(new String(threadState.bytes4, 0, length));
}
// @Benchmark
public void string1IntsCopyMemory3Bytes(BenchmarkState state, ThreadState threadState, Blackhole bh){
final int length = 3;
state.copy(state.memory2k, 0, threadState.bytes24, length);
bh.consume(new String(threadState.bytes24, 0, length));
}
// @Benchmark
public void string1IntsCopyMemoryOffset1(BenchmarkState state, ThreadState threadState, Blackhole bh){
final int length = 1 << 2;
state.copy(state.memory2k, 1, threadState.bytes4, length);
bh.consume(new String(threadState.bytes4, 0, length));
}
@Benchmark
public void string1LongsCopyMemory(BenchmarkState state, ThreadState threadState, Blackhole bh){
final int length = 1 << 3;
state.copy(state.memory2k, 0, threadState.bytes8, length);
bh.consume(new String(threadState.bytes8, 0, length));
}
@Benchmark
public void string2LongsCopyMemory(BenchmarkState state, ThreadState threadState, Blackhole bh){
final int length = 2 << 3;
state.copy(state.memory2k, 0, threadState.bytes16, length);
bh.consume(new String(threadState.bytes16, 0, length));
}
@Benchmark
public void string3LongsCopyMemory(BenchmarkState state, ThreadState threadState, Blackhole bh){
final int length = 3 << 3;
state.copy(state.memory2k, 0, threadState.bytes24, length);
bh.consume(new String(threadState.bytes24, 0, length));
}
@Benchmark
public void string8LongsCopyMemory(BenchmarkState state, ThreadState threadState, Blackhole bh){
final int length = 8 << 3;
state.copy(state.memory2k, 0, threadState.bytes64, length);
bh.consume(new String(threadState.bytes64, 0, length));
}
@Benchmark
public void string1IntsGetInt(BenchmarkState state, ThreadState threadState, Blackhole bh){
final long v = state.readInt(0);
final byte[] bytes = threadState.bytes4;
bytes[0] = (byte) (v);
bytes[1] = (byte) ((v >>> 8));
bytes[2] = (byte) ((v >>> 16));
bytes[3] = (byte) ((v >>> 24));
bh.consume(new String(bytes, 0, 4));
}
@Benchmark
public void string1IntsGetIntAndFF(BenchmarkState state, ThreadState threadState, Blackhole bh){
final long v = state.readInt(0);
final byte[] bytes = threadState.bytes4;
bytes[0] = (byte) (v & 0xFF);
bytes[1] = (byte) ((v >>> 8) & 0xFF);
bytes[2] = (byte) ((v >>> 16) & 0xFF);
bytes[3] = (byte) ((v >>> 24) & 0xFF);
bh.consume(new String(bytes, 0, 4));
}
// @Benchmark
public void string1IntsGetInt3bytes(BenchmarkState state, ThreadState threadState, Blackhole bh){
long v = state.readInt(0);
final byte[] bytes = threadState.bytes4;
bytes[0] = (byte) (v);
bytes[1] = (byte) ((v >>> 8));
bytes[2] = (byte) ((v >>> 16));
bh.consume(new String(bytes, 0, 3));
}
@Benchmark
public void string1LongsGetLong(BenchmarkState state, ThreadState threadState, Blackhole bh){
final long v = state.readLong(0);
final byte[] bytes = threadState.bytes8;
bytes[0 + 0] = (byte) (v);
bytes[0 + 1] = (byte) (v >>> 8);
bytes[0 + 2] = (byte) (v >>> 16);
bytes[0 + 3] = (byte) (v >>> 24);
bytes[0 + 4] = (byte) (v >>> 32);
bytes[0 + 5] = (byte) (v >>> 40);
bytes[0 + 6] = (byte) (v >>> 48);
bytes[0 + 7] = (byte) (v >>> 56);
bh.consume(new String(bytes, 0, 8));
}
@Benchmark
public void string1LongsGetLongAndFF(BenchmarkState state, ThreadState threadState, Blackhole bh){
final long v = state.readLong(0);
final byte[] bytes = threadState.bytes8;
bytes[0 + 0] = (byte) (v & 0xFF);
bytes[0 + 1] = (byte) ((v >>> 8) & 0xFF);
bytes[0 + 2] = (byte) ((v >>> 16) & 0xFF);
bytes[0 + 3] = (byte) ((v >>> 24) & 0xFF);
bytes[0 + 4] = (byte) ((v >>> 32) & 0xFF);
bytes[0 + 5] = (byte) ((v >>> 40) & 0xFF);
bytes[0 + 6] = (byte) ((v >>> 48) & 0xFF);
bytes[0 + 7] = (byte) ((v >>> 56) & 0xFF);
bh.consume(new String(bytes, 0, 8));
}
@Benchmark
public void string2LongsGetLong(BenchmarkState state, ThreadState threadState, Blackhole bh){
final long v1 = state.readLong(0);
final long v2 = state.readLong(8);
final byte[] bytes = threadState.bytes16;
fillValue(bytes, 0, v1);
fillValue(bytes, 1, v2);
bh.consume(new String(bytes, 0, 16));
}
@Benchmark
public void string2LongsGetLongAndFF(BenchmarkState state, ThreadState threadState, Blackhole bh){
final long v1 = state.readLong(0);
final long v2 = state.readLong(8);
final byte[] bytes = threadState.bytes16;
bytes[0 + 0] = (byte) (v1 & 0xFF);
bytes[0 + 1] = (byte) ((v1 >>> 8) & 0xFF);
bytes[0 + 2] = (byte) ((v1 >>> 16) & 0xFF);
bytes[0 + 3] = (byte) ((v1 >>> 24) & 0xFF);
bytes[0 + 4] = (byte) ((v1 >>> 32) & 0xFF);
bytes[0 + 5] = (byte) ((v1 >>> 40) & 0xFF);
bytes[0 + 6] = (byte) ((v1 >>> 48) & 0xFF);
bytes[0 + 7] = (byte) ((v1 >>> 56) & 0xFF);
bytes[8 + 0] = (byte) (v2 & 0xFF);
bytes[8 + 1] = (byte) ((v2 >>> 8) & 0xFF);
bytes[8 + 2] = (byte) ((v2 >>> 16) & 0xFF);
bytes[8 + 3] = (byte) ((v2 >>> 24) & 0xFF);
bytes[8 + 4] = (byte) ((v2 >>> 32) & 0xFF);
bytes[8 + 5] = (byte) ((v2 >>> 40) & 0xFF);
bytes[8 + 6] = (byte) ((v2 >>> 48) & 0xFF);
bytes[8 + 7] = (byte) ((v2 >>> 56) & 0xFF);
bh.consume(new String(bytes, 0, 16));
}
@Benchmark
public void string3LongsGetLong(BenchmarkState state, ThreadState threadState, Blackhole bh){
final long v1 = state.readLong(0 << 3);
final long v2 = state.readLong(1 << 3);
final long v3 = state.readLong(2 << 3);
final byte[] bytes = threadState.bytes24;
fillValue(bytes, 0, v1);
fillValue(bytes, 1, v2);
fillValue(bytes, 2, v3);
bh.consume(new String(bytes, 0, 24));
}
@Benchmark
public void string8LongsGetLong(BenchmarkState state, ThreadState threadState, Blackhole bh){
final long v1 = state.readLong(0 << 3);
final long v2 = state.readLong(1 << 3);
final long v3 = state.readLong(2 << 3);
final long v4 = state.readLong(3 << 3);
final long v5 = state.readLong(4 << 3);
final long v6 = state.readLong(5 << 3);
final long v7 = state.readLong(6 << 3);
final long v8 = state.readLong(7 << 3);
final byte[] bytes = threadState.bytes64;
fillValue(bytes, 0, v1);
fillValue(bytes, 1, v2);
fillValue(bytes, 2, v3);
fillValue(bytes, 3, v4);
fillValue(bytes, 4, v5);
fillValue(bytes, 5, v6);
fillValue(bytes, 6, v7);
fillValue(bytes, 7, v8);
bh.consume(new String(bytes, 0, 64));
}
private void fillValue(byte[] bytes, int idx, int v) {
int offset = idx << 3;
bytes[offset + 0] = (byte) (v);
bytes[offset + 1] = (byte) (v >>> 8);
bytes[offset + 2] = (byte) (v >>> 16);
bytes[offset + 3] = (byte) (v >>> 24);
}
private void fillValue(byte[] bytes, int idx, long v) {
int offset = idx << 3;
bytes[offset + 0] = (byte) (v);
bytes[offset + 1] = (byte) (v >>> 8);
bytes[offset + 2] = (byte) (v >>> 16);
bytes[offset + 3] = (byte) (v >>> 24);
bytes[offset + 4] = (byte) (v >>> 32);
bytes[offset + 5] = (byte) (v >>> 40);
bytes[offset + 6] = (byte) (v >>> 48);
bytes[offset + 7] = (byte) (v >>> 56);
}
public static void main(String[] args) throws Throwable {
Options opt = new OptionsBuilder()
.include(StringPerfTest.class.getSimpleName())
.build();
new Runner(opt).run();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment