Created
November 17, 2016 20:19
-
-
Save travisdowns/11b4688d6f642c334927aa56ebf065a6 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
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