Sep 4, 2011

Benchmark on the synchronized statement - Java

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package benchmarksynchronization;
/**
*
* @author Tanin
*/
public class Main {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
int numOfExperiment = 100;
long sumSync = 0;
long sumNonSync = 0;
for (int numLoop=1;numLoop <= 1000000;numLoop*=10) {
long[] resultSync = new long[numOfExperiment];
long[] resultNonSync = new long[numOfExperiment];
for (int i=0;i<numOfExperiment;i++) {
resultSync[i] = benchSync(numLoop);
resultNonSync[i] = benchNonSync(numLoop);
sumSync += resultSync[i];
sumNonSync += resultNonSync[i];
}
double avgSync = (double)sumSync / numOfExperiment;
double avgNonSync = (double)sumNonSync / numOfExperiment;
System.out.print("numLoop=" +numLoop);
System.out.print(", Sync = " + (long)avgSync + "(" + (long)computeStd(resultSync,avgSync) + ")");
System.out.print(", Non-Sync = "+ (long)avgNonSync + "(" + (long)computeStd(resultNonSync,avgNonSync) + ")");
System.out.println(", Ratio = " + ((double)sumSync/sumNonSync));
}
}
static double computeStd(long[] elements, double avg) {
double sumDiff = 0;
for (int i=0;i<elements.length;i++) {
sumDiff += ((double)elements[i] - avg) * ((double)elements[i] - avg);
}
return Math.sqrt(1.0 * sumDiff / (elements.length - 1));
}
static long benchSync(int numLoop)
{
int a = 0;
Object obj = new Object();
long startTime = System.nanoTime();
for (int i=0;i<numLoop;i++)
{
synchronized(obj) {
a++;
}
}
return (System.nanoTime() - startTime);
}
static long benchNonSync(int numLoop)
{
int a = 0;
Object obj = new Object();
long startTime = System.nanoTime();
for (int i=0;i<numLoop;i++)
{
a++;
}
return (System.nanoTime() - startTime);
}
}
view raw gistfile1.java hosted with ❤ by GitHub


Here is the result:

numLoop=1, Sync = 2038(1544), Non-Sync = 1686(337), Ratio = 1.2087152971312691
numLoop=10, Sync = 7838(21776), Non-Sync = 3915(2637), Ratio = 2.0018106689004207
numLoop=100, Sync = 16021(8481), Non-Sync = 6042(5061), Ratio = 2.651660195363833
numLoop=1000, Sync = 77951(17555), Non-Sync = 10382(10837), Ratio = 7.5077016277772906
numLoop=10000, Sync = 717291(129850), Non-Sync = 27672(13501), Ratio = 25.92038803375872
numLoop=100000, Sync = 6473678(761305), Non-Sync = 167752(30223), Ratio = 38.590702576996115
numLoop=1000000, Sync = 42292846(27433724), Non-Sync = 1632998(220871), Ratio = 25.89888837255176
view raw gistfile1.txt hosted with ❤ by GitHub


It is somewhat strange that ratio for 100,000 loops is bigger than for 1,000,000 loops. Maybe JVM optimizes something for us.

Now if you are going to design a system with the synchronized statement, please beware of the performance detriment.

If you do not call the synchronized more than 10,000 times (within a minute), I would just use the statement and go with a simpler architecture design.