Author: [email protected]
Date: Wed Apr 1 12:11:09 2009
New Revision: 5147
Added:
trunk/dev/core/src/com/google/gwt/dev/util/Memory.java
Modified:
trunk/dev/core/src/com/google/gwt/dev/Compiler.java
trunk/dev/core/src/com/google/gwt/dev/Precompile.java
trunk/dev/core/src/com/google/gwt/dev/jdt/WebModeCompilerFrontEnd.java
trunk/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
trunk/dev/core/src/com/google/gwt/dev/jjs/impl/SourceGenerationVisitor.java
trunk/dev/core/src/com/google/gwt/dev/jjs/impl/ToStringGenerationVisitor.java
Log:
Added infrastructure to profile compiler memory usage.
- reporting memory usage at various points
- dumping the heap at various points
- logging changes to the Java AST
Also remove the printing of a JMethod's thrown exceptions; this will soon
go away entirely.
Review by: spoon
Modified: trunk/dev/core/src/com/google/gwt/dev/Compiler.java
==============================================================================
--- trunk/dev/core/src/com/google/gwt/dev/Compiler.java (original)
+++ trunk/dev/core/src/com/google/gwt/dev/Compiler.java Wed Apr 1 12:11:09
2009
@@ -27,6 +27,7 @@
import com.google.gwt.dev.shell.CheckForUpdates;
import com.google.gwt.dev.shell.CheckForUpdates.UpdateResult;
import com.google.gwt.dev.util.FileBackedObject;
+import com.google.gwt.dev.util.Memory;
import com.google.gwt.dev.util.PerfLogger;
import com.google.gwt.dev.util.Util;
import com.google.gwt.dev.util.arg.ArgHandlerExtraDir;
@@ -119,6 +120,12 @@
}
public static void main(String[] args) {
+ Memory.initialize();
+ if (System.getProperty("gwt.jjs.dumpAst") != null) {
+ System.out.println("Will dump AST to: "
+ + System.getProperty("gwt.jjs.dumpAst"));
+ }
+
/*
* NOTE: main always exits with a call to System.exit to terminate any
* non-daemon threads that were started in Generators. Typically, this
is to
Modified: trunk/dev/core/src/com/google/gwt/dev/Precompile.java
==============================================================================
--- trunk/dev/core/src/com/google/gwt/dev/Precompile.java (original)
+++ trunk/dev/core/src/com/google/gwt/dev/Precompile.java Wed Apr 1
12:11:09 2009
@@ -40,6 +40,7 @@
import com.google.gwt.dev.shell.CheckForUpdates;
import com.google.gwt.dev.shell.StandardRebindOracle;
import com.google.gwt.dev.shell.CheckForUpdates.UpdateResult;
+import com.google.gwt.dev.util.Memory;
import com.google.gwt.dev.util.PerfLogger;
import com.google.gwt.dev.util.Util;
import com.google.gwt.dev.util.arg.ArgHandlerDisableAggressiveOptimization;
@@ -316,6 +317,12 @@
* Performs a command-line precompile.
*/
public static void main(String[] args) {
+ Memory.initialize();
+ if (System.getProperty("gwt.jjs.dumpAst") != null) {
+ System.out.println("Will dump AST to: "
+ + System.getProperty("gwt.jjs.dumpAst"));
+ }
+
/*
* NOTE: main always exits with a call to System.exit to terminate any
* non-daemon threads that were started in Generators. Typically, this
is to
Modified:
trunk/dev/core/src/com/google/gwt/dev/jdt/WebModeCompilerFrontEnd.java
==============================================================================
--- trunk/dev/core/src/com/google/gwt/dev/jdt/WebModeCompilerFrontEnd.java
(original)
+++ trunk/dev/core/src/com/google/gwt/dev/jdt/WebModeCompilerFrontEnd.java
Wed Apr 1 12:11:09 2009
@@ -27,6 +27,7 @@
import com.google.gwt.dev.jjs.impl.FragmentLoaderCreator;
import com.google.gwt.dev.util.Empty;
import com.google.gwt.dev.util.JsniRef;
+import com.google.gwt.dev.util.Memory;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
@@ -120,6 +121,7 @@
*/
CompilationUnitDeclaration[] cuds = compile(logger,
icus.toArray(new ICompilationUnit[icus.size()]));
+ Memory.maybeDumpMemory("WebModeCompiler");
return cuds;
}
Modified:
trunk/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
==============================================================================
--- trunk/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
(original)
+++ trunk/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
Wed Apr 1 12:11:09 2009
@@ -72,6 +72,7 @@
import com.google.gwt.dev.jjs.impl.ReplaceRebinds;
import com.google.gwt.dev.jjs.impl.ReplaceRunAsyncs;
import com.google.gwt.dev.jjs.impl.ResolveRebinds;
+import com.google.gwt.dev.jjs.impl.SourceGenerationVisitor;
import com.google.gwt.dev.jjs.impl.TypeMap;
import com.google.gwt.dev.jjs.impl.TypeTightener;
import com.google.gwt.dev.js.EvalFunctionsAtTopScope;
@@ -91,9 +92,12 @@
import com.google.gwt.dev.js.ast.JsName;
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsStatement;
+import com.google.gwt.dev.util.AbstractTextOutput;
import com.google.gwt.dev.util.DefaultTextOutput;
import com.google.gwt.dev.util.Empty;
+import com.google.gwt.dev.util.Memory;
import com.google.gwt.dev.util.PerfLogger;
+import com.google.gwt.dev.util.TextOutput;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.CompilationResult;
@@ -101,6 +105,9 @@
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -346,6 +353,8 @@
allRootTypes.addAll(JProgram.INDEX_TYPES_SET);
allRootTypes.add(FragmentLoaderCreator.ASYNC_FRAGMENT_LOADER);
+ Memory.maybeDumpMemory("CompStateBuilt");
+
// Compile the source and get the compiler so we can get the parse tree
//
CompilationUnitDeclaration[] goldenCuds =
compilerFrontEnd.getCompilationUnitDeclarations(
@@ -383,11 +392,15 @@
// GenerateJavaAST can uncover semantic JSNI errors; report & abort
checkForErrors(logger, goldenCuds, true);
+ Memory.maybeDumpMemory("AstBuilt");
+
// Allow GC
goldenCuds = null;
typeMap = null;
allTypeDeclarations = null;
+ maybeDumpAST(jprogram);
+
// (3) Perform Java AST normalizations.
FixAssignmentToUnbox.exec(jprogram);
@@ -457,6 +470,8 @@
throw new InterruptedException();
}
+ maybeDumpAST(jprogram);
+
// Recompute clinits each time, they can become empty.
jprogram.typeOracle.recomputeAfterOptimizations();
didChange = false;
@@ -803,5 +818,27 @@
}
return toReturn;
+ }
+
+ private static void maybeDumpAST(JProgram jprogram) {
+ String dumpFile = System.getProperty("gwt.jjs.dumpAst");
+ if (dumpFile != null) {
+ try {
+ FileOutputStream os = new FileOutputStream(dumpFile, true);
+ final PrintWriter pw = new PrintWriter(os);
+ TextOutput out = new AbstractTextOutput(false) {
+ {
+ setPrintWriter(pw);
+ }
+ };
+ SourceGenerationVisitor v = new SourceGenerationVisitor(out);
+ v.accept(jprogram);
+ pw.flush();
+ pw.close();
+ } catch (IOException e) {
+ System.out.println("Could not dump AST");
+ e.printStackTrace();
+ }
+ }
}
}
Modified:
trunk/dev/core/src/com/google/gwt/dev/jjs/impl/SourceGenerationVisitor.java
==============================================================================
---
trunk/dev/core/src/com/google/gwt/dev/jjs/impl/SourceGenerationVisitor.java
(original)
+++
trunk/dev/core/src/com/google/gwt/dev/jjs/impl/SourceGenerationVisitor.java
Wed Apr 1 12:11:09 2009
@@ -20,7 +20,6 @@
import com.google.gwt.dev.jjs.ast.JField;
import com.google.gwt.dev.jjs.ast.JInterfaceType;
import com.google.gwt.dev.jjs.ast.JMethod;
-import com.google.gwt.dev.jjs.ast.JMethodBody;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.util.TextOutput;
@@ -43,11 +42,6 @@
*/
public class SourceGenerationVisitor extends ToStringGenerationVisitor {
- private static boolean isEmptyInitializer(JMethod x) {
- return isInitializer(x)
- && (((JMethodBody) x.getBody()).getStatements().size() == 0);
- }
-
public SourceGenerationVisitor(TextOutput textOutput) {
super(textOutput);
}
@@ -70,11 +64,9 @@
}
for (int i = 0; i < x.methods.size(); ++i) {
JMethod it = x.methods.get(i);
- if (!isEmptyInitializer(it)) {
- accept(it);
- newline();
- newline();
- }
+ accept(it);
+ newline();
+ newline();
}
closeBlock();
Modified:
trunk/dev/core/src/com/google/gwt/dev/jjs/impl/ToStringGenerationVisitor.java
==============================================================================
---
trunk/dev/core/src/com/google/gwt/dev/jjs/impl/ToStringGenerationVisitor.java
(original)
+++
trunk/dev/core/src/com/google/gwt/dev/jjs/impl/ToStringGenerationVisitor.java
Wed Apr 1 12:11:09 2009
@@ -141,10 +141,6 @@
protected static final char[] CHARS_TRY = "try ".toCharArray();
protected static final char[] CHARS_WHILE = "while ".toCharArray();
- protected static boolean isInitializer(JMethod x) {
- return x.getName().equals("$clinit") || x.getName().equals("$init");
- }
-
private boolean needSemi = true;
private boolean suppressType = false;
@@ -583,17 +579,7 @@
@Override
public boolean visit(JMethod x, Context ctx) {
- // special: transcribe clinit and init as if they were initializer
blocks
- if (isInitializer(x)) {
- if (x.isStatic()) {
- print(CHARS_STATIC);
- }
- if (!shouldPrintMethodBody()) {
- print("{...}");
- }
- } else {
- printMethodHeader(x);
- }
+ printMethodHeader(x);
if (x.isAbstract() || !shouldPrintMethodBody()) {
semi();
@@ -1028,18 +1014,6 @@
// Parameters
printParameterList(x);
-
- if (x.thrownExceptions.size() > 0) {
- print(CHARS_THROWS);
- Iterator<JClassType> iter = x.thrownExceptions.iterator();
- if (iter.hasNext()) {
- printTypeName(iter.next());
- }
- while (iter.hasNext()) {
- print(CHARS_COMMA);
- printTypeName(iter.next());
- }
- }
}
protected void printName(HasName x) {
Added: trunk/dev/core/src/com/google/gwt/dev/util/Memory.java
==============================================================================
--- (empty file)
+++ trunk/dev/core/src/com/google/gwt/dev/util/Memory.java Wed Apr 1
12:11:09 2009
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
not
+ * use this file except in compliance with the License. You may obtain a
copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
under
+ * the License.
+ */
+package com.google.gwt.dev.util;
+
+import java.io.File;
+import java.lang.management.ManagementFactory;
+import java.lang.reflect.Method;
+
+/**
+ * Utility methods for dealing with VM memory.
+ */
+public class Memory {
+
+ /**
+ * Number of times to call System.gc() before measuring the memory
+ * usage/dumping the heap. This value was arrived at through
trial-and-error
+ * on the Sun JVM; memory usage seems to stabilize after 3 to 4 runs. We
think
+ * the reason it requires multiple runs is due to the generational
aspect of
+ * garbage collection.
+ */
+ private static final int NUM_GC_COLLECTIONS = 4;
+
+ /**
+ * Set this system property to a filename suffix to dump heaps into.
+ */
+ private static final String PROPERTY_DUMP_HEAP = "gwt.memory.dumpHeap";
+
+ /**
+ * Set this system property to dump memory usage at various points.
+ */
+ private static final String PROPERTY_DUMP_MEMORY = "gwt.memory.usage";
+
+ /**
+ * Time to start measuring since the last memory measurement/dump, or
+ * application startup.
+ */
+ private static long startTime;
+
+ public static void initialize() {
+ if (System.getProperty(PROPERTY_DUMP_MEMORY) != null) {
+ System.out.println("Will print mem usage");
+ }
+ if (System.getProperty(PROPERTY_DUMP_HEAP) != null) {
+ System.out.println("Will dump heap into: *-"
+ + System.getProperty(PROPERTY_DUMP_HEAP));
+ }
+ startTime = System.currentTimeMillis();
+ }
+
+ public static void main(String[] args) {
+ initialize();
+ System.setProperty(PROPERTY_DUMP_MEMORY, "");
+ maybeDumpMemory("test");
+ }
+
+ public static void maybeDumpMemory(String info) {
+ long elapsed = System.currentTimeMillis() - startTime;
+ if (System.getProperty(PROPERTY_DUMP_MEMORY) != null) {
+ for (int i = 0; i < NUM_GC_COLLECTIONS; ++i) {
+ System.gc();
+ }
+ long heap =
ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed();
+ long nonHeap =
ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().getUsed();
+ String infoString = String.format("[%.18s]", info);
+ System.out.println(String.format(
+ "%-20s %10d heap, %10d nonheap, %10d total, %10.2fs", infoString,
+ heap, nonHeap, heap + nonHeap, (double) elapsed / 1000));
+ }
+ String dumpFile = System.getProperty(PROPERTY_DUMP_HEAP);
+ if (dumpFile != null) {
+ dumpFile = info + "-" + dumpFile;
+ new File(dumpFile).delete();
+ try {
+ Class<?> beanClass =
Class.forName("com.sun.management.HotSpotDiagnosticMXBean");
+ Object bean = ManagementFactory.newPlatformMXBeanProxy(
+ ManagementFactory.getPlatformMBeanServer(),
+ "com.sun.management:type=HotSpotDiagnostic", beanClass);
+ Method dumpHeapMethod = beanClass.getDeclaredMethod("dumpHeap",
+ String.class, Boolean.TYPE);
+ dumpHeapMethod.invoke(bean, dumpFile, true);
+ System.out.println("(" + info + ") dumped heap into: " + dumpFile);
+ } catch (Throwable e) {
+ System.err.println("Unable to dump heap");
+ e.printStackTrace();
+ }
+ }
+ // Reset for next call
+ startTime = System.currentTimeMillis();
+ }
+}
--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---