Benchmarking String Concatenation in Java

by Szymon Lipiński

Last time I was checking speed of Java primitives. It turned out that Integer is much slower than int. This time I want to check how much slower is the String concatenation compared to the StringBuffer and the StringBuilder.

Concatenating Strings

Strings in Java are immutable. It means that you cannot change the variable value. When you write something like this:

    String x = "123";
    x = "456";

Java will create both strings and keep them in memory. The string "123" will be later deleted by the garbage collector, but let’s forget the GC for a while.

In the following case:

    String x = "123";
    x = x + "456";

Java will create three Strings:

    "123"
    "456"
    "123456"

That’s because Java cannot change the String data once it is created. Instead JVM creates another String variable.

StringBuffer

The StringBuffer is a class which stores all added strings in a collection. They are concatenated only when you call the function toString(). This way building the string is deferred and adding strings is not creating additional temporary strings.

StringBuilder

The StringBuilder class behaves behaves almost exactly like StringBuffer. The only difference is that it is not synchronized. That also means that is should be faster.

The Benchmark Code

The main test function looks like this:

    public void test(int maxLoops) {

        String buffer = "";

        int max = maxLoops;

        for (int index = 0; index < max; index++) {
            buffer += index + index;
        }
    }

The above is the String version. The StringBuffer version is:

    public void test(int maxLoops) {

        StringBuffer buffer = new StringBuffer();

        int max = maxLoops;

        for (int index = 0; index < max; index++) {
            buffer.append(index + index);
        }

        String x = buffer.toString();
    }

Version for StringBuilder is similar, I’ve just replaced StringBuffer with StringBuilder in the above code.

There is some logic for running the tests, but it is not important now.

The Test Machine

My test machine is my old notebook.

    64bit Ubuntu Linux 10.10 (maverick)
    Linux 2.6.35-23-generic
    4GB RAM
    Intel Core2 Duo T8100 @ 2.10GHz

Java is a normal Java from repositories, installed automatically by apt-get something.

    java version "1.6.0_22"
    Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
    Java HotSpot(TM) 64-Bit Server VM (build 17.1-b03, mixed mode)

Results

The test procedure is similar to the previous one. I will just skip to the end, after the HotSpot optimization. I don’t want to check here how HotSpot works, just to find the difference between the three ways of concatenating strings.

Hot Spot Check

Here are results for the first and last run. The test run was made by running the functions with 10,000 as the parameter.

Variable Type First Dry Run [ms] Second HotSpot Run [ms] Difference [ms] Difference [%]
String 855 572.0 283.00 51.00%
StringBuffer 4 0.6 3.40 467.00%
String 10 0.6 9.38 1.41%

HotSpot made a good job once again. Nice. The difference between String and the rest is amazing.

Data Types Hot Spot Run
String / StringBuffer 940.00
String / StringBuilder 1007.14

Well, the difference is great. I wasn’t expecting that to be so huge.

The only problem with the results is that the difference between the StringBuffer, and the StringBuilder results is really small. The time results for those classes after HotSpot run are exactly the same. The reason is I think that those classes are really fast, and the parameter 10,000 was too small.

So let’s run that with a little bit bigger one.

Comparing the StringBuffer and the StringBuilder

Now those functions were run with 15,000,000 as the parameter. Hot Spot should be really hot then.

Variable Type First Dry Run [ms] Second HotSpot Run [ms] Difference [ms] Difference [%]
StringBuffer 2763.0 1839.0 924.0 33.44%
StringBuilder 2074.0 1738.0 336.0 16.20%

Final Conclusion

String concatenation is really slow. It is about a thousand times slower than the other solutions.

The more interesting part is that it looks like the difference between StringBuffer and StringBuilder is really small. StringBuilder is faster, but only by about 5%.

Yes, you should really avoid String concatenating in Java code.