Peephole optimization of SymbolMapsLinker.

Hoist up and reuse a ByteArrayOutputStream and especially StringBuffer.  This linker has a MUCH better memory/gc profile when we can avoid creating tons of temporary buffers over and over.  We also reuse a char[] to transfer data from StringBuffer to PrintWriter to avoid having to create intermediate Strings.

Review by: spoon, fabbott

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5402 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/core/linker/SymbolMapsLinker.java b/dev/core/src/com/google/gwt/core/linker/SymbolMapsLinker.java
index fb260a5..9082a2a 100644
--- a/dev/core/src/com/google/gwt/core/linker/SymbolMapsLinker.java
+++ b/dev/core/src/com/google/gwt/core/linker/SymbolMapsLinker.java
@@ -58,14 +58,15 @@
 
     artifacts = new ArtifactSet(artifacts);
 
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
     for (CompilationResult result : artifacts.find(CompilationResult.class)) {
-      ByteArrayOutputStream out = new ByteArrayOutputStream();
       PrintWriter pw = new PrintWriter(out);
 
       doWriteSymbolMap(logger, result, pw);
       pw.close();
 
       doEmitSymbolMap(logger, artifacts, result, out);
+      out.reset();
     }
 
     return artifacts;
@@ -109,12 +110,16 @@
     }
 
     pw.println("# jsName, jsniIdent, className, memberName, sourceUri, sourceLine");
+    StringBuilder sb = new StringBuilder(1024);
+    char[] buf = new char[1024];
     for (SymbolData symbol : result.getSymbolMap()) {
-      StringBuilder sb = new StringBuilder(1024);
       sb.append(symbol.getSymbolName());
 
       sb.append(',');
-      sb.append(symbol.getJsniIdent());
+      String jsniIdent = symbol.getJsniIdent();
+      if (jsniIdent != null) {
+        sb.append(jsniIdent);
+      }
       sb.append(',');
       sb.append(symbol.getClassName());
       sb.append(',');
@@ -130,7 +135,18 @@
       sb.append(',');
       sb.append(symbol.getSourceLine());
       sb.append('\n');
-      pw.write(sb.toString());
+
+      int sbLen = sb.length();
+      if (buf.length < sbLen) {
+        int bufLen = buf.length;
+        while (bufLen < sbLen) {
+          bufLen <<= 1;
+        }
+        buf = new char[bufLen];
+      }
+      sb.getChars(0, sbLen, buf, 0);
+      pw.write(buf, 0, sbLen);
+      sb.setLength(0);
     }
   }
 }