Created
February 21, 2016 10:18
-
-
Save vladimirdolzhenko/e69bf3a7c44eb6660163 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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