Skip to content

Commit

Permalink
Add some code size metrics to the Performance Tracker knowing how man…
Browse files Browse the repository at this point in the history
…y 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
  • Loading branch information
concavelenz authored and dimvar committed Aug 18, 2016
1 parent e02980d commit b26cf72
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 16 deletions.
2 changes: 1 addition & 1 deletion src/com/google/javascript/jscomp/Compiler.java
Expand Up @@ -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());
}

Expand Down
58 changes: 48 additions & 10 deletions src/com/google/javascript/jscomp/PerformanceTracker.java
Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand All @@ -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.
Expand All @@ -95,7 +102,8 @@ public final class PerformanceTracker {
/** Stats for each run of a compiler pass. */
private final List<Stats> 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);
Expand Down Expand Up @@ -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;
}
}
}

Expand Down Expand Up @@ -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));
}
Expand Down Expand Up @@ -321,7 +353,13 @@ public int compare(Entry<String, Stats> e1, Entry<String, Stats> 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");
Expand Down
Expand Up @@ -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) {}

Expand Down
12 changes: 9 additions & 3 deletions test/com/google/javascript/jscomp/PerformanceTrackerTest.java
Expand Up @@ -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
Expand Down Expand Up @@ -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(
Expand All @@ -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);
Expand Down
4 changes: 3 additions & 1 deletion test/com/google/javascript/jscomp/PhaseOptimizerTest.java
Expand Up @@ -36,6 +36,7 @@
*/
public final class PhaseOptimizerTest extends TestCase {
private final List<String> passesRun = new ArrayList<>();
private Node dummyExternsRoot;
private Node dummyRoot;
private PhaseOptimizer optimizer;
private Compiler compiler;
Expand All @@ -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);
}

Expand Down

0 comments on commit b26cf72

Please sign in to comment.