Skip to content

Instantly share code, notes, and snippets.

@kabutz
Created November 28, 2021 11:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kabutz/3b4d499abe083d7c4185d60b2bba9591 to your computer and use it in GitHub Desktop.
Save kabutz/3b4d499abe083d7c4185d60b2bba9591 to your computer and use it in GitHub Desktop.
package richardstartin;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OperationsPerInvocation;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.infra.Blackhole;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
@State(Scope.Benchmark)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@BenchmarkMode(Mode.AverageTime)
public class CompositeLookup {
record Pair(String s1, String s2) {
}
@Param("1024")
int size;
Map<String, Object> concatMap;
Map<Pair, Object> pairMap;
String[] prefixes;
String[] suffixes;
String[][] prefixesGroup = new String[1024][];
String[][] suffixesGroup = new String[1024][];
Thread hashCodeResettingThread;
@Setup(Level.Trial)
public void setup() {
prefixes = new String[size];
suffixes = new String[size];
concatMap = new HashMap<>();
pairMap = new HashMap<>();
for (int i = 0; i < size; ++i) {
prefixes[i] = UUID.randomUUID().toString();
suffixes[i] = UUID.randomUUID().toString();
concatMap.put(prefixes[i] + ";" + suffixes[i], i);
// use new String to avoid reference equality speeding up the equals calls
pairMap.put(new Pair(new String(prefixes[i]), new String(suffixes[i])), i);
}
for (int i = 0; i < prefixesGroup.length; i++) {
prefixesGroup[i] = Stream.of(prefixes).map(this::refresh).toArray(String[]::new);
suffixesGroup[i] = Stream.of(suffixes).map(this::refresh).toArray(String[]::new);
}
hashCodeResettingThread = new Thread(() -> {
while(!Thread.currentThread().isInterrupted()) {
for (int i = 0; i < prefixesGroup.length; i++) {
for (int j = 0; j < prefixesGroup[i].length; j++) {
prefixesGroup[i][j] = refresh(prefixes[j]);
suffixesGroup[i][j] = refresh(suffixes[j]);
}
}
}
});
hashCodeResettingThread.start();
}
private int pos;
private static final VarHandle STRING_HASH;
static {
try {
STRING_HASH = MethodHandles.privateLookupIn(String.class, MethodHandles.lookup())
.findVarHandle(String.class, "hash", int.class);
} catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
private String refresh(String s) {
STRING_HASH.set(s, 0);
return s;
}
@TearDown
public void tearDown() {
hashCodeResettingThread.interrupt();
}
@Benchmark
@OperationsPerInvocation(1024)
public void concatenate(Blackhole bh) {
String[] prefixes = this.prefixesGroup[pos];
String[] suffixes = this.suffixesGroup[pos];
if (++pos == prefixesGroup.length) pos = 0;
for (int i = 0; i < prefixes.length; ++i) {
bh.consume(concatMap.get(prefixes[i] + ";" + suffixes[i]));
}
}
@Benchmark
@OperationsPerInvocation(1024)
public void wrap(Blackhole bh) {
String[] prefixes = this.prefixesGroup[pos];
String[] suffixes = this.suffixesGroup[pos];
if (++pos == prefixesGroup.length) pos = 0;
for (int i = 0; i < prefixes.length; ++i) {
bh.consume(pairMap.get(new Pair(prefixes[i], suffixes[i])));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment