Created
October 30, 2014 18:33
-
-
Save duarten/0cfcb642440fbb94bc59 to your computer and use it in GitHub Desktop.
Concurrent maps benchmarks
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 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]; | |
} | |
} |
Author
duarten
commented
Oct 30, 2014
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment