I am trying to create a little benchmark (in Groovy) that shows high thread contention on a couple of synchronized methods. High contention should show up when monitoring voluntary context switches, and in Linux this can be achieved thanks to "pidstat".
The program is the following:
class Res {
private int n;
synchronized public void inc() {
n++;
def foo = []
for (int i = 0; i < 1000; ++i) foo << "hello"
}
synchronized public int getN() {
return n;
}
}
while (true) {
Res res = new Res()
int N = 100000
for (int i = 0; i < N; ++i) {
new Thread({
res.inc()
if (res.getN() == N) {
println "ok"
}
}).start()
}
while (res.getN() < N) {
}
println "========================="
}
but the command
pidstat -w -I -p 26848 5
is printing 0 on the voluntary context switches column. The program creates 100000 thread that concurrently access a synchronized method. I can't believe that with such workload, no context switching is happening.
What's wrong with my benchmark?
解决方案
Your command displays statistics for the main thread only, child PIDs are not counted.
Hotspot JVM has internal synchronization counters, but some magic is needed in order to unlock them:
Run jconsole.exe -J-Djconsole.showUnsupported and connect to your JVM.
Select Connection -> Hotspot MBeans -> Create from the main menu.
Open sun.management.HotspotRuntime on the MBeans tab.
You'll find a bunch of counters under InternalRuntimeCounters attribute:
sun.rt._sync_ContendedLockAttempts
sun.rt._sync_Parks
sun.rt._sync_Notifications
sun.rt._sync_Inflations
etc.