Benchmarking String Concatenation in Java
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.