Skip to content

Instantly share code, notes, and snippets.

@duarten
Created October 30, 2014 18:33
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save duarten/0cfcb642440fbb94bc59 to your computer and use it in GitHub Desktop.
Save duarten/0cfcb642440fbb94bc59 to your computer and use it in GitHub Desktop.
Concurrent maps benchmarks
import java.util.HashMap;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import scala.collection.concurrent.TrieMap;
import org.openjdk.jmh.annotations.*;
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 5)
@Measurement(iterations = 5, time = 2)
@Fork(5)
@Threads(Threads.MAX)
public class HashMapBenchmark {
static final int numValues = 10240; // Power of 2
static final int mask = numValues - 1;
@State(Scope.Benchmark)
public static class JavaMap {
public UUID[] uuids;
public HashMap<UUID, Object> map;
@Setup
public void setup() {
map = new HashMap<>();
uuids = new UUID[numValues];
for (int i = 0; i < numValues; ++i) {
uuids[i] = UUID.randomUUID();
Object value = new Object();
map.put(uuids[i], value);
}
}
}
@State(Scope.Benchmark)
public static class ConcurrentMap {
public UUID[] uuids = new UUID[numValues];
public ConcurrentHashMap<UUID, Object> map;
@Setup
public void setup() {
map = new ConcurrentHashMap<>();
uuids = new UUID[numValues];
for (int i = 0; i < numValues; ++i) {
uuids[i] = UUID.randomUUID();
Object value = new Object();
map.put(uuids[i], value);
}
}
}
@State(Scope.Benchmark)
public static class ScalaTrieMap {
public UUID[] uuids = new UUID[numValues];
public TrieMap<UUID, Object> map;
@Setup
public void setup() {
map = new TrieMap<>();
uuids = new UUID[numValues];
for (int i = 0; i < numValues; ++i) {
uuids[i] = UUID.randomUUID();
Object value = new Object();
map.put(uuids[i], value);
}
}
}
@State(Scope.Thread)
public static class Index {
public int value;
@Setup
public void setup() {
value = (int) (Thread.currentThread().getId() * System.nanoTime() * 31);
}
}
// Read throughput
@Benchmark
public Object measureReadJava(JavaMap state, Index index) {
return state.map.get(getUuid(state.uuids, index));
}
@Benchmark
public Object measureReadConcurrent(ConcurrentMap state, Index index) {
return state.map.get(getUuid(state.uuids, index));
}
@Benchmark
public Object measureReadTrie(ScalaTrieMap state, Index index) {
return state.map.get(getUuid(state.uuids, index)).get();
}
// Write throughput
@Benchmark
@Threads(1)
public Object measureWriteJava(JavaMap state, Index index) {
return state.map.put(getUuid(state.uuids, index), state);
}
@Benchmark
@Threads(1)
public Object measureWriteConcurrent(ConcurrentMap state, Index index) {
return state.map.put(getUuid(state.uuids, index), state);
}
@Benchmark
@Threads(1)
public Object measureWriteTrie(ScalaTrieMap state, Index index) {
return state.map.put(getUuid(state.uuids, index), state);
}
// Readers with concurrent writer
@Benchmark
@Group("readsAndWritesTrie")
public Object measureReadersWithWriters(ScalaTrieMap state, Index index) {
return state.map.get(getUuid(state.uuids, index)).get();
}
@Benchmark
@Group("readsAndWritesTrie")
@GroupThreads(1)
public Object measureWriter(ScalaTrieMap state, Index index) {
int idx = index.value++ & mask;
UUID key = (idx & 1) == 0 ? state.uuids[idx] : UUID.randomUUID();
return state.map.put(key, state);
}
@Benchmark
@Group("readsAndWritesConcurrent")
public Object measureReadersWithWritersConc(ConcurrentMap state, Index index) {
return state.map.get(getUuid(state.uuids, index));
}
@Benchmark
@Group("readsAndWritesConcurrent")
@GroupThreads(1)
public Object measureWriterConc(ConcurrentMap state, Index index) {
int idx = index.value++ & mask;
UUID key = (idx & 1) == 0 ? state.uuids[idx] : UUID.randomUUID();
return state.map.put(key, state);
}
// Readers with concurrent remove
@Benchmark
@Group("readsAndRemovesTrie")
public Object measureReadersWithRemovers(ScalaTrieMap state, Index index) {
return state.map.get(getUuid(state.uuids, index));
}
@Benchmark
@Group("readsAndRemovesTrie")
@GroupThreads(1)
public Object measureRemover(ScalaTrieMap state, Index index) {
return state.map.remove(getUuid(state.uuids, index));
}
@Benchmark
@Group("readsAndRemovesConcurrent")
public Object measureReadersWithRemoversConc(ConcurrentMap state, Index index) {
return state.map.get(getUuid(state.uuids, index));
}
@Benchmark
@Group("readsAndRemovesConcurrent")
@GroupThreads(1)
public Object measureRemoverConc(ConcurrentMap state, Index index) {
return state.map.remove(getUuid(state.uuids, index));
}
// Utility method
@CompilerControl(CompilerControl.Mode.INLINE)
public UUID getUuid(UUID[] uuids, Index index) {
return uuids[index.value++ & mask];
}
}
@duarten
Copy link
Author

duarten commented Oct 30, 2014

Benchmark                                                   Mode  Samples     Score      Error  Units
measureReadConcurrent                                       avgt       25    29.416 ±    0.742  ns/op
measureReadJava                                             avgt       25    17.916 ±    0.410  ns/op
measureReadTrie                                             avgt       25    77.748 ±    0.693  ns/op
measureWriteConcurrent                                      avgt       25    44.745 ±    1.195  ns/op
measureWriteJava                                            avgt       25    14.700 ±    0.844  ns/op
measureWriteTrie                                            avgt       25   149.920 ±    3.984  ns/op
readsAndRemovesConcurrent                                   avgt       25    57.344 ±    2.196  ns/op
readsAndRemovesConcurrent:measureReadersWithRemoversConc    avgt       25    31.125 ±    1.162  ns/op
readsAndRemovesConcurrent:measureRemoverConc                avgt       25    83.564 ±    3.427  ns/op
readsAndRemovesTrie                                         avgt       25    67.056 ±    1.267  ns/op
readsAndRemovesTrie:measureReadersWithRemovers              avgt       25    62.078 ±    2.258  ns/op
readsAndRemovesTrie:measureRemover                          avgt       25    72.033 ±    0.975  ns/op
readsAndWritesConcurrent                                    avgt       25  1906.960 ±  337.109  ns/op
readsAndWritesConcurrent:measureReadersWithWritersConc      avgt       25    70.386 ±    8.575  ns/op
readsAndWritesConcurrent:measureWriterConc                  avgt       25  3743.534 ±  666.485  ns/op
readsAndWritesTrie                                          avgt       25  2776.069 ±  969.338  ns/op
readsAndWritesTrie:measureReadersWithWriters                avgt       25   319.412 ±   96.278  ns/op
readsAndWritesTrie:measureWriter                            avgt       25  5232.726 ± 1846.638  ns/op

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment