What really stinks about using a StringBuffer (and therefore the + operator) is that append's are synchronized!! To really see an impact on performance, use a custom string buffer class that is not thread safe and use StringBuffers only where thead safety is required.
Regards, --mike On Fri, 26 Oct 2001, Sylvain Wallez wrote: > > Berin Loritsch a écrit : > > > > Friends, going through the source code looking for > > places to optimize the critical path (i.e. the path > > taken when no error or log message is performed), > > I went through adding StringBuffers where there were > > three or more strings to concatenate. > > > > I found an enigma. > > > > In several places, where the code was already using > > a StringBuffer, I found code snippets like this: > > > > buffer.append("<" + prefix + ":" + name + "/>"); > > > > This gets expanded into the much more complex code as > > follows: > > > > buffer.append( > > new StringBuffer( > > new StringBuffer( > > new StringBuffer( > > new StringBuffer("<").append(prefix).toString() > > ).append(":").toString() > > ).append(name).toString() > > ).append("/>").toString() > > ); > > > > That means four additional StringBuffers were created > > behind the scenes. This is ludicrous when we are already > > using StringBuffers--and wasteful of resources. > > > > Instead, please write the code to explicitly take advantage > > of the StringBuffer when it is available: > > > > buffer.append("<").append(prefix).append(":").append(name).append("/>"); > > > > This is more respectful of the environment, and is much quicker > > to execute on any JVM. > > > > Please, be mindful in the future. > > Berin, > > Having once looked at the generated bytecode for string concatenation, I > came to the conclusion that replacing "+" on Strings by append() on > StringBuffers is really not worth it as far as performance is concerned, > apart of course in the above case which involves concatenation in > appends (and a strange compiler behaviour). > > Take the following example. The two methods do exactly the same thing, > one with String concatenation, and the other one with > StringBuffer.append(). > > package proto; > public class TestSBuff { > > public void test1(int i, String msg) { > System.out.println("The value " > + "of i is " > + i > + " and the value of msg is '" > + msg > + "'"); > } > > public void test2(int i, String msg) { > System.out.println(new StringBuffer("The value ") > .append("of i is ") > .append(i) > .append(" and the value of msg is '") > .append(msg) > .append("'") > .toString()); > } > } > > Here's the resulting bytecode, output with javap -c : > > Compiled from TestSBuff.java > public class proto.TestSBuff extends java.lang.Object { > public proto.TestSBuff(); > public void test1(int, java.lang.String); > public void test2(int, java.lang.String); > } > > Method proto.TestSBuff() > 0 aload_0 > 1 invokespecial #1 <Method java.lang.Object()> > 4 return > > Method void test1(int, java.lang.String) > 0 getstatic #2 <Field java.io.PrintStream out> > 3 new #3 <Class java.lang.StringBuffer> > 6 dup > 7 invokespecial #4 <Method java.lang.StringBuffer()> > 10 ldc #5 <String "The value of i is "> > 12 invokevirtual #6 <Method java.lang.StringBuffer > append(java.lang.String)> > 15 iload_1 > 16 invokevirtual #7 <Method java.lang.StringBuffer append(int)> > 19 ldc #8 <String " and the value of msg is '"> > 21 invokevirtual #6 <Method java.lang.StringBuffer > append(java.lang.String)> > 24 aload_2 > 25 invokevirtual #6 <Method java.lang.StringBuffer > append(java.lang.String)> > 28 ldc #9 <String "'"> > 30 invokevirtual #6 <Method java.lang.StringBuffer > append(java.lang.String)> > 33 invokevirtual #10 <Method java.lang.String toString()> > 36 invokevirtual #11 <Method void println(java.lang.String)> > 39 return > > Method void test2(int, java.lang.String) > 0 getstatic #2 <Field java.io.PrintStream out> > 3 new #3 <Class java.lang.StringBuffer> > 6 dup > 7 ldc #12 <String "The value "> > 9 invokespecial #13 <Method java.lang.StringBuffer(java.lang.String)> > 12 ldc #14 <String "of i is "> > 14 invokevirtual #6 <Method java.lang.StringBuffer > append(java.lang.String)> > 17 iload_1 > 18 invokevirtual #7 <Method java.lang.StringBuffer append(int)> > 21 ldc #8 <String " and the value of msg is '"> > 23 invokevirtual #6 <Method java.lang.StringBuffer > append(java.lang.String)> > 26 aload_2 > 27 invokevirtual #6 <Method java.lang.StringBuffer > append(java.lang.String)> > 30 ldc #9 <String "'"> > 32 invokevirtual #6 <Method java.lang.StringBuffer > append(java.lang.String)> > 35 invokevirtual #10 <Method java.lang.String toString()> > 38 invokevirtual #11 <Method void println(java.lang.String)> > 41 return > > Two things are shown above : > > * String concatenation is translated to StringBuffer.append() > instructions. The only difference with direct StringBuffer code is that > the default no-arg StringBuffer() constructor is called and the first > string is appended like others. I'm not sure this small benefit > justifies the decreased code readability (and the increased keyboard > typing ;) > > * Constant String concatenation (like "The value " + "of i is ") isn't > translated to individual StringBuffer.append(), but to a single String > constant ("The value of i is "). In that case, performance is better > with String concatenation. This means some of the changes you made on > code where constant strings are concatenated to allow line-splitting > (see for example WildcardURIMatcherFactory) are in fact slowing down the > code ! > > The conclusion is that StringBuffer is only worth it when the > concatenation occurs in several statements, or iteratively such as in a > "for" loop. Otherwhise, single-statement String concatenations can be > considered equivalent to their StringBuffer translation, but produce > less readable code. > > Sylvain. > > -- > Sylvain Wallez > Anyware Technologies - http://www.anyware-tech.com > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, email: [EMAIL PROTECTED] > --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]