Skip to content

Instantly share code, notes, and snippets.

@travisdowns
Created November 17, 2016 20:19
Show Gist options
  • Save travisdowns/11b4688d6f642c334927aa56ebf065a6 to your computer and use it in GitHub Desktop.
Save travisdowns/11b4688d6f642c334927aa56ebf065a6 to your computer and use it in GitHub Desktop.
package foo;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.LongAdder;
import java.util.function.BiConsumer;
public class Main {
static final int THREADS = 8;
static final ExecutorService executor = Executors.newFixedThreadPool(THREADS);
static final CompletionService<Result> completion = new ExecutorCompletionService<Result>(executor);
public static class Result {};
public static void benchGetPut0Adder(String[] words, ConcurrentHashMap<String, Object> chm) {
for (String word : words) {
LongAdder count = (LongAdder)chm.get(word);
if (count == null) {
LongAdder existing = (LongAdder)chm.putIfAbsent(word, count = new LongAdder());
count = existing == null ? count : existing;
}
count.increment();
}
// topWord(chm);
}
public static void benchGetPut0(String[] words, ConcurrentHashMap<String, Object> chm) {
for (String word : words) {
AtomicInteger count = (AtomicInteger)chm.get(word);
if (count == null) {
AtomicInteger existing = (AtomicInteger)chm.putIfAbsent(word, count = new AtomicInteger());
count = existing == null ? count : existing;
}
count.incrementAndGet();
}
// topWord(chm);
}
public static void benchGetPut1(String[] words, ConcurrentHashMap<String, Object> chm) {
for (String word : words) {
AtomicInteger count = (AtomicInteger)chm.get(word);
if (count == null) {
if ((count = (AtomicInteger)chm.putIfAbsent(word, new AtomicInteger(1))) == null) {
continue;
}
}
count.incrementAndGet();
}
// topWord(chm);
}
public static void benchComputeIfAbsent(String[] words, ConcurrentHashMap<String, Object> chm) {
for (String word : words) {
AtomicInteger count = (AtomicInteger)chm.computeIfAbsent(word, s -> new AtomicInteger());
count.incrementAndGet();
}
// topWord(chm);
}
public static void topWord(ConcurrentHashMap<String, AtomicInteger> chm) {
Entry<String, AtomicInteger> entry = chm.entrySet().stream().max((e1, e2) -> e1.getValue().get() - e2.getValue().get()).get();
System.out.println("most common word: " + entry.getKey() + " : " + entry.getValue());
}
public static void bench(String name, BiConsumer<String[], ConcurrentHashMap<String, Object>> benchmark, List<String[]> words) throws InterruptedException {
long start = System.currentTimeMillis();
ConcurrentHashMap<String, Object> chm = new ConcurrentHashMap<>();
for (final String[] partition : words) {
completion.submit(() -> { benchmark.accept(partition, chm); return null; });
}
long results[] = new long[words.size()];
for (int i=0; i < words.size(); i++) {
completion.take();
results[i] = System.currentTimeMillis() - start;
}
System.out.println(String.format("%35s: %d ms %s", name, (System.currentTimeMillis() - start), Arrays.toString(results)));
}
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(new File("enwik8"), "utf-8");
List<String> wordlist = new ArrayList<>();
while (scanner.hasNext()) {
wordlist.add(scanner.next());
wordlist.add("the");
}
String[] words = wordlist.toArray(new String[wordlist.size()]);
System.out.println("Read " + words.length + " words");
List<String[]> partition = partition(words);
bench("get -> pufIfAbsent0", Main::benchGetPut0, partition);
bench("get -> pufIfAbsent1", Main::benchGetPut1, partition);
bench("get -> pufIfAbsentAdder", Main::benchGetPut0Adder, partition);
bench("get -> benchComputeIfAbsent", Main::benchComputeIfAbsent, partition);
bench("get -> pufIfAbsent0", Main::benchGetPut0, partition);
bench("get -> pufIfAbsent1", Main::benchGetPut1, partition);
bench("get -> pufIfAbsentAdder", Main::benchGetPut0Adder, partition);
bench("get -> benchComputeIfAbsent", Main::benchComputeIfAbsent, partition);
bench("get -> pufIfAbsent0", Main::benchGetPut0, partition);
bench("get -> pufIfAbsent1", Main::benchGetPut1, partition);
bench("get -> pufIfAbsentAdder", Main::benchGetPut0Adder, partition);
bench("get -> benchComputeIfAbsent", Main::benchComputeIfAbsent, partition);
bench("get -> pufIfAbsent0", Main::benchGetPut0, partition);
bench("get -> pufIfAbsent1", Main::benchGetPut1, partition);
bench("get -> pufIfAbsentAdder", Main::benchGetPut0Adder, partition);
bench("get -> benchComputeIfAbsent", Main::benchComputeIfAbsent, partition);
bench("get -> pufIfAbsent0", Main::benchGetPut0, partition);
bench("get -> pufIfAbsent1", Main::benchGetPut1, partition);
bench("get -> pufIfAbsentAdder", Main::benchGetPut0Adder, partition);
bench("get -> benchComputeIfAbsent", Main::benchComputeIfAbsent, partition);
bench("get -> pufIfAbsent0", Main::benchGetPut0, partition);
bench("get -> pufIfAbsent1", Main::benchGetPut1, partition);
bench("get -> pufIfAbsentAdder", Main::benchGetPut0Adder, partition);
bench("get -> benchComputeIfAbsent", Main::benchComputeIfAbsent, partition);
scanner.close();
executor.shutdown();
}
private static List<String[]> partition(String[] words) {
List<String[]> ret = new ArrayList<>();
for (int i=1, last = 0; i <= THREADS; i++) {
int next = words.length * i / THREADS;
int size = next - last;
String[] p = new String[size];
System.arraycopy(words, last, p, 0, size);
last = next;
ret.add(p);
}
return ret;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment