From b26cf727f3b533f9f6539e2559dcabbdbdc504e3 Mon Sep 17 00:00:00 2001 From: johnlenz Date: Wed, 17 Aug 2016 14:57:22 -0700 Subject: [PATCH] Add some code size metrics to the Performance Tracker knowing how many file/lines the compiler is dealing with on a build will help scope performance issues. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=130567205 --- .../google/javascript/jscomp/Compiler.java | 2 +- .../javascript/jscomp/PerformanceTracker.java | 58 +++++++++++++++---- .../javascript/jscomp/PerformanceTracker.java | 2 +- .../jscomp/PerformanceTrackerTest.java | 12 +++- .../javascript/jscomp/PhaseOptimizerTest.java | 4 +- 5 files changed, 62 insertions(+), 16 deletions(-) diff --git a/src/com/google/javascript/jscomp/Compiler.java b/src/com/google/javascript/jscomp/Compiler.java index 9c182850ea6..50a64289c24 100644 --- a/src/com/google/javascript/jscomp/Compiler.java +++ b/src/com/google/javascript/jscomp/Compiler.java @@ -1403,7 +1403,7 @@ Node parseInputs() { jsRoot.detachChildren(); if (options.tracer.isOn()) { - tracker = new PerformanceTracker(jsRoot, options.tracer, this.outStream); + tracker = new PerformanceTracker(externsRoot, jsRoot, options.tracer, this.outStream); addChangeHandler(tracker.getCodeChangeHandler()); } diff --git a/src/com/google/javascript/jscomp/PerformanceTracker.java b/src/com/google/javascript/jscomp/PerformanceTracker.java index 075e9501af2..985d19868fb 100644 --- a/src/com/google/javascript/jscomp/PerformanceTracker.java +++ b/src/com/google/javascript/jscomp/PerformanceTracker.java @@ -24,6 +24,7 @@ import com.google.common.collect.ImmutableMap; import com.google.javascript.jscomp.CompilerOptions.TracerMode; import com.google.javascript.rhino.Node; +import com.google.javascript.rhino.StaticSourceFile; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -58,6 +59,7 @@ public final class PerformanceTracker { private final OutputStreamWriter output; private final Node jsRoot; + private final Node externsRoot; private final boolean trackSize; private final boolean trackGzSize; @@ -75,6 +77,11 @@ public final class PerformanceTracker { private int loopRuns = 0; private int loopChanges = 0; + private int jsLines = 0; + private int jsSources = 0; + private int externLines = 0; + private int externSources = 0; + // The following fields for tracking size changes are just estimates. // They do not take into account preserved license blocks, newline padding, // or pretty printing (if enabled), since they don't use CodePrinter. @@ -95,7 +102,8 @@ public final class PerformanceTracker { /** Stats for each run of a compiler pass. */ private final List log = new ArrayList<>(); - PerformanceTracker(Node jsRoot, TracerMode mode, PrintStream printStream) { + PerformanceTracker(Node externsRoot, Node jsRoot, TracerMode mode, PrintStream printStream) { + this.externsRoot = externsRoot; this.jsRoot = jsRoot; this.printStream = printStream == null ? System.out : printStream; this.output = new OutputStreamWriter(this.printStream, UTF_8); @@ -158,14 +166,17 @@ void recordPassStop(String passName, long runtime) { } // After parsing, initialize codeSize and gzCodeSize - if (passName.equals(Compiler.PARSING_PASS_NAME) && trackSize) { - CodeSizeEstimatePrinter estimatePrinter = new CodeSizeEstimatePrinter(); - CodeGenerator.forCostEstimation(estimatePrinter).add(jsRoot); - initCodeSize = codeSize = estimatePrinter.calcSize(); - logStats.size = summaryStats.size = initCodeSize; - if (this.trackGzSize) { - initGzCodeSize = gzCodeSize = estimatePrinter.calcZippedSize(); - logStats.gzSize = summaryStats.gzSize = initGzCodeSize; + if (passName.equals(Compiler.PARSING_PASS_NAME)) { + recordInputCount(); + if (trackSize) { + CodeSizeEstimatePrinter estimatePrinter = new CodeSizeEstimatePrinter(); + CodeGenerator.forCostEstimation(estimatePrinter).add(jsRoot); + initCodeSize = codeSize = estimatePrinter.calcSize(); + logStats.size = summaryStats.size = initCodeSize; + if (this.trackGzSize) { + initGzCodeSize = gzCodeSize = estimatePrinter.calcZippedSize(); + logStats.gzSize = summaryStats.gzSize = initGzCodeSize; + } } } @@ -201,6 +212,27 @@ void recordPassStop(String passName, long runtime) { } } + private void recordInputCount() { + for (Node n : externsRoot.children()) { + this.externSources += 1; + this.externLines += estimateLines(n); + } + + for (Node n : jsRoot.children()) { + this.jsSources += 1; + this.jsLines += estimateLines(n); + } + } + + private int estimateLines(Node n) { + Preconditions.checkState(n.isScript()); + StaticSourceFile ssf = n.getStaticSourceFile(); + if (ssf != null && ssf instanceof SourceFile) { + return ((SourceFile) ssf).getNumLines(); + } + return 0; + } + private int bytesToMB(long bytes) { return (int) (bytes / (1024 * 1024)); } @@ -321,7 +353,13 @@ public int compare(Entry e1, Entry e2) { + "\n#Changing runs: " + changes + "\n#Loopable runs: " + loopRuns + "\n#Changing loopable runs: " + loopChanges + "\nEstimated Reduction(bytes): " + diff + "\nEstimated GzReduction(bytes): " + gzDiff + "\nEstimated Size(bytes): " + codeSize - + "\nEstimated GzSize(bytes): " + gzCodeSize + "\n\n"); + + "\nEstimated GzSize(bytes): " + gzCodeSize + "\n"); + + this.output.write("\nInputs:" + + "\nJS lines: " + jsLines + + "\nJS sources: " + jsSources + + "\nExtern lines: " + externLines + + "\nExtern sources: " + externSources + "\n\n"); this.output.write("Log:\n" + "pass,runtime,allocMem,codeChanged,reduction,gzReduction,size,gzSize\n"); diff --git a/src/com/google/javascript/jscomp/gwt/super/com/google/javascript/jscomp/PerformanceTracker.java b/src/com/google/javascript/jscomp/gwt/super/com/google/javascript/jscomp/PerformanceTracker.java index f36d5a79a41..3ea160f9f3c 100644 --- a/src/com/google/javascript/jscomp/gwt/super/com/google/javascript/jscomp/PerformanceTracker.java +++ b/src/com/google/javascript/jscomp/gwt/super/com/google/javascript/jscomp/PerformanceTracker.java @@ -23,7 +23,7 @@ /** GWT compatible no-op replacement for {@code PerformanceTracker} */ public final class PerformanceTracker { - PerformanceTracker(Node jsRoot, TracerMode mode, PrintStream pstr) {} + PerformanceTracker(Node externsRoot, Node jsRoot, TracerMode mode, PrintStream pstr) {} void recordPassStart(String passName, boolean isOneTime) {} diff --git a/test/com/google/javascript/jscomp/PerformanceTrackerTest.java b/test/com/google/javascript/jscomp/PerformanceTrackerTest.java index 5baf2ba81fd..3f71d7c0b84 100644 --- a/test/com/google/javascript/jscomp/PerformanceTrackerTest.java +++ b/test/com/google/javascript/jscomp/PerformanceTrackerTest.java @@ -36,11 +36,12 @@ * @author dimvar@google.com (Dimitris Vardoulakis) */ public final class PerformanceTrackerTest extends TestCase { - private Node emptyScript = new Node(Token.SCRIPT); + private Node emptyExternRoot = new Node(Token.BLOCK); + private Node emptyJsRoot = new Node(Token.BLOCK); public void testStatsCalculation() { PerformanceTracker tracker = - new PerformanceTracker(emptyScript, TracerMode.ALL, null); + new PerformanceTracker(emptyExternRoot, emptyJsRoot, TracerMode.ALL, null); CodeChangeHandler handler = tracker.getCodeChangeHandler(); // It's sufficient for this test to assume that a single run of any pass @@ -106,7 +107,7 @@ public void testOutputFormat() { ByteArrayOutputStream output = new ByteArrayOutputStream(); PrintStream outstream = new PrintStream(output); PerformanceTracker tracker = - new PerformanceTracker(emptyScript, TracerMode.ALL, outstream); + new PerformanceTracker(emptyExternRoot, emptyJsRoot, TracerMode.ALL, outstream); tracker.outputTracerReport(); outstream.close(); Pattern p = Pattern.compile( @@ -122,6 +123,11 @@ public void testOutputFormat() { + "\nEstimated GzReduction\\(bytes\\): [0-9]+" + "\nEstimated Size\\(bytes\\): -?[0-9]+" + "\nEstimated GzSize\\(bytes\\): -?[0-9]+" + + "\n\nInputs:" + + "\nJS lines: [0-9]+" + + "\nJS sources: [0-9]+" + + "\nExtern lines: [0-9]+" + + "\nExtern sources: [0-9]+" + "\n\nLog:\n" + "pass,runtime,allocMem,codeChanged,reduction,gzReduction,size,gzSize.*", Pattern.DOTALL); diff --git a/test/com/google/javascript/jscomp/PhaseOptimizerTest.java b/test/com/google/javascript/jscomp/PhaseOptimizerTest.java index 38ed73cadc6..32eb594c8b1 100644 --- a/test/com/google/javascript/jscomp/PhaseOptimizerTest.java +++ b/test/com/google/javascript/jscomp/PhaseOptimizerTest.java @@ -36,6 +36,7 @@ */ public final class PhaseOptimizerTest extends TestCase { private final List passesRun = new ArrayList<>(); + private Node dummyExternsRoot; private Node dummyRoot; private PhaseOptimizer optimizer; private Compiler compiler; @@ -44,12 +45,13 @@ public final class PhaseOptimizerTest extends TestCase { @Override public void setUp() { passesRun.clear(); + dummyExternsRoot = new Node(Token.BLOCK); dummyRoot = new Node(Token.BLOCK); // Needed if we are validating the AST using AstValidator. dummyRoot.setIsSyntheticBlock(true); compiler = new Compiler(); compiler.initCompilerOptionsIfTesting(); - tracker = new PerformanceTracker(dummyRoot, TracerMode.TIMING_ONLY, null); + tracker = new PerformanceTracker(dummyExternsRoot, dummyRoot, TracerMode.TIMING_ONLY, null); optimizer = new PhaseOptimizer(compiler, tracker, null); }