Core Java

Can synchronization be optimised away?

Overview

There is a common misconception that because the JIT is smart and synchronization can be eliminated for an object which is only local to a method that there is no performance impact.
 
 
 
 
 
 

A test comparing StringBuffer and StringBuilder

These two classes do basically the same thing except one is synchronized (StringBuffer) and the other is not. It is also a class which is often used in one method to build a String.  The following test attempts to determine how much difference using one other the other can make.

static String dontOptimiseAway = null;
static String[] words = new String[100000];

public static void main(String... args) {
    for (int i = 0; i < words.length; i++)
        words[i] = Integer.toString(i);

    for (int i = 0; i < 10; i++) {
        dontOptimiseAway = testStringBuffer();
        dontOptimiseAway = testStringBuilder();
    }
}

private static String testStringBuffer() {
    long start = System.nanoTime();
    StringBuffer sb = new StringBuffer();
    for (String word : words) {
        sb.append(word).append(',');
    }
    String s = sb.substring(0, sb.length() - 1);
    long time = System.nanoTime() - start;
    System.out.printf("StringBuffer: took %d ns per word%n", time / words.length);
    return s;
}

private static String testStringBuilder() {
    long start = System.nanoTime();
    StringBuilder sb = new StringBuilder();
    for (String word : words) {
        sb.append(word).append(',');
    }
    String s = sb.substring(0, sb.length() - 1);
    long time = System.nanoTime() - start;
    System.out.printf("StringBuilder: took %d ns per word%n", time / words.length);
    return s;
}

at the end prints with -XX:+DoEscapeAnalysis using Java 7 update 10

StringBuffer: took 69 ns per word
StringBuilder: took 32 ns per word
StringBuffer: took 88 ns per word
StringBuilder: took 26 ns per word
StringBuffer: took 62 ns per word
StringBuilder: took 25 ns per word

Testing with one million words doesn’t change the results significantly.

Conclusion

  • While the cost of using synchronization is small, it is measurable and if you can use StringBuilder it is preferred as it states in the Javadocs for this class.
  • In theory, synchronization can be optimised away, but it is yet to be the case even in simple cases.

 

Reference: Can synchronization be optimised away? from our JCG partner Peter Lawrey at the Vanilla Java blog.

Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

3 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Micha Riser
Micha Riser
11 years ago

Micro-benchmarking is hard. Your numbers are not reflecting the results of the full-optimization of the JIT. If you run the tests 10000 times instead of 10 times the numbers change! On my computer: Initially: StringBuffer: took 67 ns per word StringBuilder: took 18 ns per word StringBuffer: took 64 ns per word StringBuilder: took 19 ns per word … but the on run 10000: StringBuffer: took 42 ns per word StringBuilder: took 28 ns per word StringBuffer: took 39 ns per word StringBuilder: took 29 ns per word The gap is much smaller. To get more consistent numbers, use a… Read more »

ikk
ikk
11 years ago
Reply to  Micha Riser

Well, I’d still use the faster class anyway. It’s good to know that if my method is run very often it will get faster, but if it does not run that often I want those extra milliseconds to do something else :-)

ikk
ikk
11 years ago

I wonder why synchronization was added in Java at the class level. When you are writing a class, you don’t know if it’s going to be used in local variables or in a static shared variable, so how can you decide about synchronization?

Back to top button