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.

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

JPA Mini Book

Learn how to leverage the power of JPA in order to create robust and flexible Java applications. With this Mini Book, you will get introduced to JPA and smoothly transition to more advanced concepts.

JVM Troubleshooting Guide

The Java virtual machine is really the foundation of any Java EE platform. Learn how to master it with this advanced guide!

Given email address is already subscribed, thank you!
Oops. Something went wrong. Please try again later.
Please provide a valid email address.
Thank you, your sign-up request was successful! Please check your e-mail inbox.
Please complete the CAPTCHA.
Please fill in the required fields.

3 Responses to "Can synchronization be optimised away?"

  1. Micha Riser says:

    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 micro-benchmarking framework which adapts the run count automatically and filters out values from unoptimized runs. As an example I use JBenchX (http://iquadrat.github.com/jbenchx):

    import org.jbenchx.annotations.Bench;

    public class SynchronizedBench {
    private final String[] words = new String[100000];
    public SynchronizedBench() {
    for (int i = 0; i < words.length; i++) {
    words[i] = Integer.toString(i);
    }
    }
    @Bench(divisor = 100000)
    public String testStringBuffer() {
    StringBuffer sb = new StringBuffer();
    for (String word : words) {
    sb.append(word).append(',');
    }
    return sb.substring(0, sb.length() – 1);
    }
    @Bench(divisor = 100000)
    public String testStringBuilder() {
    StringBuilder sb = new StringBuilder();
    for (String word : words) {
    sb.append(word).append(',');
    }
    return sb.substring(0, sb.length() – 1);
    }
    }

    which gives the numbers:
    [0] SynchronizedBench.testStringBuffer****.*.*..*…* 26.2ns
    [1] SynchronizedBench.testStringBuilder.****.**** 22.1ns

    which is really close to each other

    • ikk says:

      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 :-)

  2. ikk says:

    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?

Leave a Reply


9 × six =



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy | Contact
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close