Hi Tom, Would that it were so, but Java's handling of concatenation is woefully suboptimal where variables are involved. I'm attaching a couple of files as examples of this. The first is a simple class which implements the same string creation code in two ways: once using concatenation operations, and again using StringBuffer.append() operations. The second file is the output of the bytecode disassembler on the compiled class. You'll note that the bytecodes for the concat() method contain repeated calls to new StringBuffer() and then to toString() -- one for each instance of the overloaded "+=" operator. The result is a lot of extra GC thrash for methods that use the concat() approach.
Eric -----Original Message----- From: Tom Jordahl [mailto:[EMAIL PROTECTED] Sent: Monday, July 07, 2003 11:58 AM To: '[EMAIL PROTECTED]' Subject: RE: cvs commit: xml-axis/java/src/org/apache/axis AxisFault.java Eric, My understanding was that Java would "take care of that" when it encountered string concatenation. It would convert the x = a + b + c + .. + z; in to code that would do the "smart" appending. And the other way was easier to read. :-) P.S. Welcome to Open Source! -- Tom Jordahl Macromedia Server Development -----Original Message----- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] Sent: Friday, June 27, 2003 1:43 AM To: [EMAIL PROTECTED] Subject: cvs commit: xml-axis/java/src/org/apache/axis AxisFault.java ericf 2003/06/26 22:43:03 Modified: java/src/org/apache/axis AxisFault.java Log: replaced extensive String concatenation code with equivalent StringBuffer.append code to reduce object creation Revision Changes Path 1.80 +32 -38 xml-axis/java/src/org/apache/axis/AxisFault.java Index: AxisFault.java =================================================================== RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/AxisFault.java,v retrieving revision 1.79 retrieving revision 1.80 diff -u -r1.79 -r1.80 --- AxisFault.java 29 May 2003 11:59:56 -0000 1.79 +++ AxisFault.java 27 Jun 2003 05:43:03 -0000 1.80 @@ -313,49 +313,43 @@ */ public String dumpToString() { - String details = new String(); - + StringBuffer buf = new StringBuffer("AxisFault"); + buf.append(JavaUtils.LS); + buf.append(" faultCode: "); + buf.append(XMLUtils.xmlEncodeString(faultCode.toString())); + buf.append(JavaUtils.LS); + buf.append(" faultSubcode: "); + if (faultSubCode != null) { + for (int i = 0; i < faultSubCode.size(); i++) { + buf.append(JavaUtils.LS); + buf.append(faultSubCode.elementAt(i).toString()); + } + } + buf.append(JavaUtils.LS); + buf.append(" faultString: "); + buf.append(XMLUtils.xmlEncodeString(faultString)); + buf.append(JavaUtils.LS); + buf.append(" faultActor: "); + buf.append(XMLUtils.xmlEncodeString(faultActor)); + buf.append(JavaUtils.LS); + buf.append(" faultNode: "); + buf.append(XMLUtils.xmlEncodeString(faultNode)); + buf.append(JavaUtils.LS); + buf.append(" faultDetail: "); if (faultDetails != null) { for (int i=0; i < faultDetails.size(); i++) { Element e = (Element) faultDetails.get(i); - String namespace= e.getNamespaceURI(); - if(namespace==null) { - namespace=""; - } - String partname= e.getLocalName(); - if(partname==null) { - partname=e.getNodeName(); - } - details += JavaUtils.LS - + "\t{" + namespace + "}" - + partname + ": " - + XMLUtils.getInnerXMLString(e); - } - } - - String subCodes = new String(); - if (faultSubCode != null) { - for (int i = 0; i < faultSubCode.size(); i++) { - subCodes += JavaUtils.LS - + (QName)faultSubCode.elementAt(i); + buf.append(JavaUtils.LS); + buf.append("\t{"); + buf.append(null == e.getNamespaceURI() ? "" : e.getNamespaceURI()); + buf.append("}"); + buf.append(null == e.getLocalName() ? "" : e.getLocalName()); + buf.append(":"); + buf.append(XMLUtils.getInnerXMLString(e)); } } - //encode everything except details and subcodes, which are already - //dealt with one way or another. - String code= XMLUtils.xmlEncodeString(faultCode.toString()); - String errorString= XMLUtils.xmlEncodeString(faultString); - String actor= XMLUtils.xmlEncodeString(faultActor); - String node= XMLUtils.xmlEncodeString(faultNode); - - - return "AxisFault" + JavaUtils.LS - + " faultCode: " + code + JavaUtils.LS - + " faultSubcode: " + subCodes + JavaUtils.LS - + " faultString: " + errorString + JavaUtils.LS - + " faultActor: " + actor + JavaUtils.LS - + " faultNode: " + node + JavaUtils.LS - + " faultDetail: " + details + JavaUtils.LS - ; + buf.append(JavaUtils.LS); + return buf.toString(); } /**
test.java
Description: Binary data
Compiled from test.java
public class test extends java.lang.Object {
static int variable;
public test();
static java.lang.String concat();
static java.lang.String append();
static java.lang.String makeString();
}
Method test()
0 aload_0
1 invokespecial #1 <Method java.lang.Object()>
4 return
Method java.lang.String concat()
0 ldc #2 <String "">
2 astore_0
3 new #3 <Class java.lang.StringBuffer>
6 dup
7 invokespecial #4 <Method java.lang.StringBuffer()>
10 aload_0
11 invokevirtual #5 <Method java.lang.StringBuffer append(java.lang.String)>
14 ldc #6 <String "a">
16 invokevirtual #5 <Method java.lang.StringBuffer append(java.lang.String)>
19 invokevirtual #7 <Method java.lang.String toString()>
22 astore_0
23 new #3 <Class java.lang.StringBuffer>
26 dup
27 invokespecial #4 <Method java.lang.StringBuffer()>
30 aload_0
31 invokevirtual #5 <Method java.lang.StringBuffer append(java.lang.String)>
34 invokestatic #8 <Method java.lang.String makeString()>
37 invokevirtual #5 <Method java.lang.StringBuffer append(java.lang.String)>
40 invokevirtual #7 <Method java.lang.String toString()>
43 astore_0
44 new #3 <Class java.lang.StringBuffer>
47 dup
48 invokespecial #4 <Method java.lang.StringBuffer()>
51 aload_0
52 invokevirtual #5 <Method java.lang.StringBuffer append(java.lang.String)>
55 ldc #9 <String "b">
57 invokevirtual #5 <Method java.lang.StringBuffer append(java.lang.String)>
60 invokevirtual #7 <Method java.lang.String toString()>
63 astore_0
64 new #3 <Class java.lang.StringBuffer>
67 dup
68 invokespecial #4 <Method java.lang.StringBuffer()>
71 aload_0
72 invokevirtual #5 <Method java.lang.StringBuffer append(java.lang.String)>
75 ldc #10 <String "c">
77 invokevirtual #5 <Method java.lang.StringBuffer append(java.lang.String)>
80 invokevirtual #7 <Method java.lang.String toString()>
83 astore_0
84 aload_0
85 areturn
Method java.lang.String append()
0 new #3 <Class java.lang.StringBuffer>
3 dup
4 invokespecial #4 <Method java.lang.StringBuffer()>
7 astore_0
8 aload_0
9 ldc #6 <String "a">
11 invokevirtual #5 <Method java.lang.StringBuffer append(java.lang.String)>
14 pop
15 aload_0
16 invokestatic #8 <Method java.lang.String makeString()>
19 invokevirtual #5 <Method java.lang.StringBuffer append(java.lang.String)>
22 pop
23 aload_0
24 ldc #9 <String "b">
26 invokevirtual #5 <Method java.lang.StringBuffer append(java.lang.String)>
29 pop
30 aload_0
31 ldc #10 <String "c">
33 invokevirtual #5 <Method java.lang.StringBuffer append(java.lang.String)>
36 pop
37 aload_0
38 invokevirtual #7 <Method java.lang.String toString()>
41 areturn
Method java.lang.String makeString()
0 new #3 <Class java.lang.StringBuffer>
3 dup
4 invokespecial #4 <Method java.lang.StringBuffer()>
7 ldc #11 <String "some">
9 invokevirtual #5 <Method java.lang.StringBuffer append(java.lang.String)>
12 getstatic #12 <Field int variable>
15 dup
16 iconst_1
17 iadd
18 putstatic #12 <Field int variable>
21 invokevirtual #13 <Method java.lang.StringBuffer append(int)>
24 invokevirtual #7 <Method java.lang.String toString()>
27 areturn
