Last active
January 1, 2016 17:29
-
-
Save pdsouza/8177312 to your computer and use it in GitHub Desktop.
Thread contention microbenchmark
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.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(); | |
} | |
} |
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
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