Skip to content

Instantly share code, notes, and snippets.

@pdsouza
Last active January 1, 2016 17:29
Show Gist options
  • Save pdsouza/8177312 to your computer and use it in GitHub Desktop.
Save pdsouza/8177312 to your computer and use it in GitHub Desktop.
Thread contention microbenchmark
import java.util.concurrent.atomic.AtomicInteger;
/**
* Simple thread contention microbenchmark consisting of
* concurrently updating a shared counter a bunch of times.
*
* Synchronization strategies used:
* (1) intrinsic monitor lock
* (2) compare-and-swap atomic instruction via AtomicInteger
*/
public class ContentionTest {
final static int N = 50000000;
final static int MAX_THREADS = 4; // # cores
static int x = 0;
static Object xLock = new Object();
static AtomicInteger ax = new AtomicInteger(0);
public static void main(String[] args) throws InterruptedException {
long start = System.nanoTime();
runContentionTest(1, new IncStrategy() { // this really makes me want lambda expressions NOW
public void inc() {
++x;
}
});
System.out.println("1 thread no lock: " + (System.nanoTime() - start)/1000000.0 + " ms");
for(int i = 1; i <= MAX_THREADS; ++i) {
x = 0;
start = System.nanoTime();
runContentionTest(i, new IncStrategy() {
public void inc() {
synchronized(xLock) { // use an intrinsic monitor lock
++x;
}
}
});
System.out.println(i + " thread(s) with lock: " + (System.nanoTime() - start)/1000000.0 + " ms");
}
for(int i = 1; i <= MAX_THREADS; ++i) {
ax.getAndSet(0);
start = System.nanoTime();
runContentionTest(i, new IncStrategy() {
public void inc() {
ax.getAndIncrement(); // atomic with memory barriers, so no lock!
}
});
System.out.println(i + " thread(s) atomic: " + (System.nanoTime() - start)/1000000.0 + " ms");
}
}
private static void runContentionTest(int numThreads, IncStrategy s) throws InterruptedException {
Thread threads[] = new Thread[numThreads];
for(int i = 0; i < numThreads; ++i) {
threads[i] = new Thread(new IncThread(s));
}
for(int i = 0; i < numThreads; ++i) {
threads[i].start();
}
for(int i = 0; i < numThreads; ++i) {
threads[i].join();
}
}
private static class IncThread implements Runnable {
private IncStrategy s;
public IncThread(IncStrategy s) {
this.s = s;
}
public void run() {
for(int i = 0; i < N; ++i) {
s.inc();
}
}
}
private static interface IncStrategy {
public void inc();
}
}
Output on dual core 2.5 Ghz Intel Core i5 with HyperThreading on MacBook Pro running OS X 10.8.5
$ java ContentionTest
1 thread no lock: 14.028 ms
1 thread(s) with lock: 1229.04 ms
2 thread(s) with lock: 4116.048 ms
3 thread(s) with lock: 5850.103 ms
4 thread(s) with lock: 7776.914 ms
1 thread(s) atomic: 585.375 ms
2 thread(s) atomic: 3141.459 ms
3 thread(s) atomic: 11461.463 ms
4 thread(s) atomic: 20841.65 ms
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment