StringBuilder's performance lower than that of StringBuffer

Hi,

I read in many websites than StringBuilder offers better performance than StringBuffer. So, in my code, I changed all StringBuffer usages to StringBuilder. But now the performance has worsened. Is it that StringBuffer is really more performant? Also, is there any better performant way than using StringBuilder & StringBuffer?

Thanks.

[361 byte] By [GSPa] at [2007-10-3 3:28:04]
# 1
StringBuilder is not synchronized, thus usually quicker. What are you doing? What's your code? How did you test?
CeciNEstPasUnProgrammeura at 2007-7-14 21:21:35 > top of Java-index,Java Essentials,Java Programming...
# 2
Hi,Mainly, the code uses StringBuffer's append method to append characters to it. This append method seems to take nearly 60% of CPU time!Thanks
GSPa at 2007-7-14 21:21:35 > top of Java-index,Java Essentials,Java Programming...
# 3
> Mainly, the code uses StringBuffer's append method to> append characters to it. This append method seems to> take nearly 60% of CPU time!Doesn't mean anything. Please post your code and tell us how you measured the performance.
CeciNEstPasUnProgrammeura at 2007-7-14 21:21:35 > top of Java-index,Java Essentials,Java Programming...
# 4

Hi,

There are 100s of snippets of code here & there in the application which use StringBuilder's appen(). Pasting few here:

1.

s = new StringBuffer((s + "").substring(0,(s + "").indexOf("</QUERY>")));

s.append(finalMapString);

s.append("</QUERY>");

2.

StringBuffer stringBuffer = new StringBuffer();

stringBuffer.append(rootDirectory).append(File.separator).append(visitorResult.getRSQID()).append(visitorResult.getSequence()).append(".").append(visitorResult.getDataFileType());

3.

private StringBuffer output = new StringBuffer();

output.append("<" + tagName) ;

In all the above code, I had simply replaced StringBuffer with StringBuilder & measured performance i.e. CPU time usage using profiler.

Thanks.

GSPa at 2007-7-14 21:21:35 > top of Java-index,Java Essentials,Java Programming...
# 5

Example #2 test:

import java.io.*;

class TestRunner {

static final int TEST_RUNS = 10;

public static void main(String[] args) throws Exception {

VisitorResult result = new VisitorResult();

String rootDirectory = "root";

Test[] tests = {

new StringBufTest(rootDirectory, result),

new StringBldTest(rootDirectory, result)

};

for (int i = 0; i < TEST_RUNS; i++) {

for (Test t : tests) {

t.execute();

clean();

}

System.out.println("\n \n");

}

}

static void clean() {

for (int i = 0; i < 3; i++) System.gc();

System.runFinalization();

try { Thread.sleep(100); } catch (Exception e) { }

}

}

interface Test {

void execute() throws Exception ;

}

abstract class AbstractTest implements Test {

static final int ITERATIONS = 100000;

abstract void doTest() throws Exception;

public void execute() throws Exception {

long start = System.currentTimeMillis();

for (int i = 0; i < ITERATIONS; i++) {

doTest();

}

long finish = System.currentTimeMillis();

long elapsed = finish - start;

printResults(elapsed);

}

private void printResults(long elapsed) {

System.out.printf("%s (%d iterations) -> total elapsed: %6d millis, average: %.6f millis\n",

getClass().getName(), ITERATIONS, elapsed, (double) elapsed / ITERATIONS);

}

}

class StringBufTest extends AbstractTest {

private String rootDirectory;

private VisitorResult visitorResult;

StringBufTest(String rootDirectory, VisitorResult result) {

this.rootDirectory = rootDirectory;

this.visitorResult = result;

}

void doTest() throws Exception {

StringBuffer stringBuffer = new StringBuffer();

stringBuffer.append(rootDirectory)

.append(File.separator)

.append(visitorResult.getRSQID())

.append(visitorResult.getSequence())

.append(".")

.append(visitorResult.getDataFileType());

}

}

class StringBldTest extends AbstractTest {

private String rootDirectory;

private VisitorResult visitorResult;

StringBldTest(String rootDirectory, VisitorResult result) {

this.rootDirectory = rootDirectory;

this.visitorResult = result;

}

void doTest() throws Exception {

StringBuilder stringBuilder = new StringBuilder();

stringBuilder.append(rootDirectory)

.append(File.separator)

.append(visitorResult.getRSQID())

.append(visitorResult.getSequence())

.append(".")

.append(visitorResult.getDataFileType());

}

}

class VisitorResult {

String getRSQID() { return "rsqid"; }

String getSequence() { return "sequence"; }

String getDataFileType() { return "datafiletype"; }

}

Results:

StringBufTest (100000 iterations) -> total elapsed:62 millis, average: 0.000620 millis

StringBldTest (100000 iterations) -> total elapsed:63 millis, average: 0.000630 millis

StringBufTest (100000 iterations) -> total elapsed:78 millis, average: 0.000780 millis

StringBldTest (100000 iterations) -> total elapsed:47 millis, average: 0.000470 millis

StringBufTest (100000 iterations) -> total elapsed:109 millis, average: 0.001090 millis

StringBldTest (100000 iterations) -> total elapsed:78 millis, average: 0.000780 millis

StringBufTest (100000 iterations) -> total elapsed:94 millis, average: 0.000940 millis

StringBldTest (100000 iterations) -> total elapsed:46 millis, average: 0.000460 millis

StringBufTest (100000 iterations) -> total elapsed:62 millis, average: 0.000620 millis

StringBldTest (100000 iterations) -> total elapsed:47 millis, average: 0.000470 millis

StringBufTest (100000 iterations) -> total elapsed:79 millis, average: 0.000790 millis

StringBldTest (100000 iterations) -> total elapsed:47 millis, average: 0.000470 millis

StringBufTest (100000 iterations) -> total elapsed:78 millis, average: 0.000780 millis

StringBldTest (100000 iterations) -> total elapsed:47 millis, average: 0.000470 millis

StringBufTest (100000 iterations) -> total elapsed:62 millis, average: 0.000620 millis

StringBldTest (100000 iterations) -> total elapsed:62 millis, average: 0.000620 millis

StringBufTest (100000 iterations) -> total elapsed:62 millis, average: 0.000620 millis

StringBldTest (100000 iterations) -> total elapsed:47 millis, average: 0.000470 millis

StringBufTest (100000 iterations) -> total elapsed:63 millis, average: 0.000630 millis

StringBldTest (100000 iterations) -> total elapsed:47 millis, average: 0.000470 millis

yawmarka at 2007-7-14 21:21:35 > top of Java-index,Java Essentials,Java Programming...
# 6
This is all insignificant. How much execution time do you think you're going to save with this exercise? Personally I would be using new File(path,name) for most of what your test code does.
ejpa at 2007-7-14 21:21:36 > top of Java-index,Java Essentials,Java Programming...
# 7

> This is all insignificant. How much execution time do

> you think you're going to save with this exercise?

Is this directed at me? If so, I'm not hoping to save any execution time with this exercise. I was just taking a break this afternoon. I posted the results of the tests to show that the difference between using StringBuffer and StringBuilder at the level of the OP's demonstration is pretty much irrelevant in any practical sense.

> Personally I would be using new File(path,name) for

> most of what your test code does.

Personally, I would too (well, probably just "new File(path)"). But I wanted to run the test using as similar code as could get to the examples the OP used as demonstrations of what was causing so much trouble.

~

yawmarka at 2007-7-14 21:21:36 > top of Java-index,Java Essentials,Java Programming...
# 8
> Is this directed at me?No, at the OP of course. We are in agreement.
ejpa at 2007-7-14 21:21:36 > top of Java-index,Java Essentials,Java Programming...
# 9
> > Is this directed at me?> > No, at the OP of course. We are in agreement.Okay; thanks for clarifying. I was confused (obviously). :o)~
yawmarka at 2007-7-14 21:21:36 > top of Java-index,Java Essentials,Java Programming...
# 10

U have messed u with String ,String Builder, and StringBuffer

StringBuffer is better than String as StringBuffer object holds 16 bits of extra memory than actually it requires for the first time.

When u append more characters to StringBuffer object memory is always available hence no need to reallocte it ,which is the case for String.

vipuluckya at 2007-7-14 21:21:36 > top of Java-index,Java Essentials,Java Programming...
# 11

> StringBuffer is better than String as StringBuffer

No, it's just different. They serve different purposes.

> object holds 16 bits of extra memory than actually it

> requires for the first time.

I haven't looked, but I highly doubt this is the case.

> When u append more characters to StringBuffer object

> memory is always available

> hence no need to reallocte

No. There may be extra space initially, but if you append enough, you'll use that up and have to allocate more.

> it ,which is the case for String.

That's not the whole picture. String is immutable. You can't change a String's contents after creation. It's not just a matter of allocating more memory. (You'll have to do that, but it will be in a completely new String object.)

jverda at 2007-7-14 21:21:36 > top of Java-index,Java Essentials,Java Programming...
# 12

> StringBuffer is better than String as StringBuffer

No, it's just different. They serve different purposes.

> object holds 16 bits of extra memory than actually it

> requires for the first time.

I haven't looked, but I highly doubt this is the case.

===u can reffer 'complete reference'

also u cancheck StringBuffer constructor which allows u to explicity specify buffer size

> When u append more characters to StringBuffer object

> memory is always available

> hence no need to reallocte

No. There may be extra space initially, but if you append enough, you'll use that up and have to allocate more.

===

if u try to append anything less than 16 char its works fine

but if u exceed it(say 25)

new space of(25-16)+16 will be allocated.

> it ,which is the case for String.

That's not the whole picture. String is immutable. You can't change a String's contents after creation. It's not just a matter of allocating more memory. (You'll have to do that, but it will be in a completely new String object.)

String function internally carrys out the same operation of string buffer whenever its contents are altered but doesn't hold any more space as its doesn't support append func directly.

vipuluckya at 2007-7-14 21:21:36 > top of Java-index,Java Essentials,Java Programming...
# 13

> > object holds 16 bits of extra memory than actually

> it

> > requires for the first time.

>

> I haven't looked, but I highly doubt this is the

> case.

> ===u can reffer 'complete reference'

> also u cancheck StringBuffer constructor which allows

> u to explicity specify buffer size

The above makes no sense. Try to write more clearly. Whatever you're trying to say, though, it seems very different from "holds 16 bits of extra memory than actually it requires for the first time."

>

> > When u append more characters to StringBuffer

> object

> > memory is always available

> > hence no need to reallocte

>

> No. There may be extra space initially, but if you

> append enough, you'll use that up and have to

> allocate more.

> ===

> if u try to append anything less than 16 char its

> works fine

> but if u exceed it(say 25)

> new space of(25-16)+16 will be allocated.

Yes. But:

* You said 16 bits. Maybe you meant 17 bytes?

* You said "memory is always available, hence no need to reallocate it." But, as I said, if you use up more than what's initially available, the StringBuffer will have to allocate more. Perhaps you meant that you don't have to create a new object like you do with String. This is true, but it's because String is immutable.

> > it ,which is the case for String.

>

> That's not the whole picture. String is immutable.

> You can't change a String's contents after creation.

> It's not just a matter of allocating more memory.

> (You'll have to do that, but it will be in a

> completely new String object.)

>

> String function internally carrys out the same

> operation of string buffer whenever its contents are

> altered but doesn't hold any more space as its

> doesn't support append func directly.

No. String is immutable. You cannot change its contents after creation. That is the key difference betwen String and StringBuffer/Builder.

jverda at 2007-7-14 21:21:36 > top of Java-index,Java Essentials,Java Programming...
# 14

is string really mutuable

try out

String s="Good";

System.out.println(s);

s="Best";

System.out.println(s);

see if u get any complier errors,run time and so on

Back to StringBuffer

1. StringBuffer sb=new StringBuffer("hi");

System.out.println(sb +" Length"+sb.length());

sb.append(" Friend");

System.out.println(sb +" Length"+sb.length());

sb.append(" its going to be a great day ,isn't it");

System.out.println(sb +" Length"+sb.length());

try out men

vipuluckya at 2007-7-14 21:21:36 > top of Java-index,Java Essentials,Java Programming...
# 15

> is string really mutuable

No.

> try out

>

> String s="Good";

> System.out.println(s);

> s="Best";

> System.out.println(s);

So where did any String change here? You just reassigned the reference to a new object.

[ _ ] You know what a reference is.

[ _ ] You know that the assignment operator does assignments

[ X ] You should study the basics again

CeciNEstPasUnProgrammeura at 2007-7-21 10:11:21 > top of Java-index,Java Essentials,Java Programming...
# 16

> is string really mutuable

No. As I stated, it is immutable.

> try out

>

> String s="Good";

> System.out.println(s);

> s="Best";

> System.out.println(s);

You're not changing the contents of a String object. You're just pointing the reference variable at a different String object.

As I said, String is immutable: You cannot change the contents of a String object.

> Back to StringBuffer

Irrelevant.

jverda at 2007-7-21 10:11:21 > top of Java-index,Java Essentials,Java Programming...
# 17
vipulucky:final StringBuffer sb = new StringBuffer();So StringBuffer is suddenly immutable? I don't think so.
CeciNEstPasUnProgrammeura at 2007-7-21 10:11:21 > top of Java-index,Java Essentials,Java Programming...