Optimised String Concatenation?

K

Kamal Advani

Hello,

Sorry if this topic has been beaten to death, or if there's an FAQ
(kindly point me to it); I'm a bit baffled by the following behaviour:

-----------

public void testTiming() {
long start, stop;

start = System.currentTimeMillis();
for (int i=0; i < 1000; i++) {
getStrBuff(""+new Date()+new Date()+new Date()+new Date());
}
stop = System.currentTimeMillis();
System.out.println("strbuff took (in ms): " + (stop - start));

start = System.currentTimeMillis();
for (int i=0; i < 1000; i++) {
getStrCat(""+new Date()+new Date()+new Date()+new Date());
}
stop = System.currentTimeMillis();
System.out.println("strcat took (in ms): " + (stop - start));
}

private String getStrBuff(String x) {
return new StringBuffer("x is ").append(x).toString();
}

private String getStrCat(String x) {
return "x is " + x;
}

---------

// Output
strbuff took (in ms): 1573
strcat took (in ms): 130

---------

Why does the StringBuffer version run significantly slower (consistent
proportion across multiple runs are obtained)?

I can understand if they're String literals concatenated together, or
Strings whose values are well known in advance, allowing the compiler to
optimise at compile time into a single literal for e.g.; in this case,
dates can only be obtained at runtime - wouldn't that imply that the +
version will create StringBuffers internally?

Thanks.
 
B

Bart Cremers

To start, no offense meant, your test sucks.

You're not comparing anything there. You're testing how long it takes
to construct a stringbuffer around a string from the pool against how
long it takes to get the same thing from the pool and concatenate it.
Turn around your test and you'll be even more amazed :)

A better test would be:

public static void testTiming() {
long start, stop;

start = System.currentTimeMillis();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 1000; i++) {
sb.append(new Date());
sb.append(new Date());
sb.append(new Date());
sb.append(new Date());
}

stop = System.currentTimeMillis();
System.out.println("strbuff took (in ms): " + (stop - start));

start = System.currentTimeMillis();
String x = "";
for (int i = 0; i < 1000; i++) {
x += new Date();
x += new Date();
x += new Date();
x += new Date();
}
stop = System.currentTimeMillis();
System.out.println("strcat took (in ms): " + (stop - start));
}

which more or less shows the difference in performance there.

Regards,

Bart
 
C

Chris Uppal

Kamal said:
strbuff took (in ms): 1573
strcat took (in ms): 130

I suspect that it's nothing to do with the use of StringBuffers, but that you
have run the test for too short a time for the JIT to have fully warmed up.
Run your code inside another loop which calls testTiming():
for (;;)
{
testTiming();
}
and watch what happens. I'll be interested and surprised if the effect doesn't
vanish.

BTW, what you are timing here will mostly be the time it takes to evaluate:
""+new Date()+new Date()+new Date()+new Date()
since that will take a lot longer than the subsequent call to either
getStrBuffer() or getStrCat().

-- chris
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,586
Members
45,084
Latest member
HansGeorgi

Latest Threads

Top