Index: pkg/front_end/tool/perf.dart |
diff --git a/pkg/front_end/tool/perf.dart b/pkg/front_end/tool/perf.dart |
index af74fd33424c533597c74fb8b8634fe5acfad962..7cd3a49126cf372e330c749a62a0dfbdf9d91f00 100644 |
--- a/pkg/front_end/tool/perf.dart |
+++ b/pkg/front_end/tool/perf.dart |
@@ -6,7 +6,7 @@ |
library front_end.tool.perf; |
import 'dart:async'; |
-import 'dart:io' show exit, stderr; |
+import 'dart:io' show exit; |
import 'package:analyzer/dart/ast/ast.dart'; |
import 'package:analyzer/error/listener.dart'; |
@@ -23,33 +23,13 @@ import 'package:analyzer/src/summary/format.dart'; |
import 'package:analyzer/src/summary/idl.dart'; |
import 'package:analyzer/src/summary/link.dart'; |
import 'package:analyzer/src/summary/summarize_ast.dart'; |
-import 'package:kernel/analyzer/loader.dart'; |
-import 'package:kernel/kernel.dart'; |
-import 'package:package_config/discovery.dart'; |
- |
import 'package:front_end/compiler_options.dart'; |
import 'package:front_end/kernel_generator.dart'; |
import 'package:front_end/src/scanner/reader.dart'; |
import 'package:front_end/src/scanner/scanner.dart'; |
import 'package:front_end/src/scanner/token.dart'; |
- |
-/// Cumulative total number of chars scanned. |
-int scanTotalChars = 0; |
- |
-/// Cumulative time spent scanning. |
-Stopwatch scanTimer = new Stopwatch(); |
- |
-/// Cumulative time spent parsing. |
-Stopwatch parseTimer = new Stopwatch(); |
- |
-/// Cumulative time spent building unlinked summaries. |
-Stopwatch unlinkedSummarizeTimer = new Stopwatch(); |
- |
-/// Cumulative time spent prelinking summaries. |
-Stopwatch prelinkSummaryTimer = new Stopwatch(); |
- |
-/// Factory to load and resolve app, packages, and sdk sources. |
-SourceFactory sources; |
+import 'package:kernel/kernel.dart'; |
+import 'package:package_config/discovery.dart'; |
main(List<String> args) async { |
// TODO(sigmund): provide sdk folder as well. |
@@ -128,95 +108,74 @@ main(List<String> args) async { |
report("total", totalTimer.elapsedMicroseconds); |
} |
-/// Sets up analyzer to be able to load and resolve app, packages, and sdk |
-/// sources. |
-Future setup(Uri entryUri) async { |
- var provider = PhysicalResourceProvider.INSTANCE; |
- var packageMap = new ContextBuilder(provider, null, null) |
- .convertPackagesToMap(await findPackages(entryUri)); |
- sources = new SourceFactory([ |
- new ResourceUriResolver(provider), |
- new PackageMapUriResolver(provider, packageMap), |
- new DartUriResolver( |
- new FolderBasedDartSdk(provider, provider.getFolder("sdk"))), |
- ]); |
-} |
+/// Cumulative time spent parsing. |
+Stopwatch parseTimer = new Stopwatch(); |
-/// Load and scans all files we need to process: files reachable from the |
-/// entrypoint and all core libraries automatically included by the VM. |
-Set<Source> scanReachableFiles(Uri entryUri) { |
- var files = new Set<Source>(); |
- var loadTimer = new Stopwatch()..start(); |
- collectSources(sources.forUri2(entryUri), files); |
+/// Cumulative time spent prelinking summaries. |
+Stopwatch prelinkSummaryTimer = new Stopwatch(); |
- var libs = [ |
- "dart:async", |
- "dart:collection", |
- "dart:convert", |
- "dart:core", |
- "dart:developer", |
- "dart:_internal", |
- "dart:isolate", |
- "dart:math", |
- "dart:mirrors", |
- "dart:typed_data", |
- "dart:io" |
- ]; |
+/// Cumulative time spent scanning. |
+Stopwatch scanTimer = new Stopwatch(); |
- for (var lib in libs) { |
- collectSources(sources.forUri(lib), files); |
- } |
+/// Cumulative total number of chars scanned. |
+int scanTotalChars = 0; |
- loadTimer.stop(); |
+/// Factory to load and resolve app, packages, and sdk sources. |
+SourceFactory sources; |
- print('input size: ${scanTotalChars} chars'); |
- var loadTime = loadTimer.elapsedMicroseconds - scanTimer.elapsedMicroseconds; |
- report("load", loadTime); |
- report("scan", scanTimer.elapsedMicroseconds); |
- return files; |
-} |
+/// Cumulative time spent building unlinked summaries. |
+Stopwatch unlinkedSummarizeTimer = new Stopwatch(); |
-/// Scans every file in [files] and reports the time spent doing so. |
-void scanFiles(Set<Source> files) { |
- // The code below will record again how many chars are scanned and how long it |
- // takes to scan them, even though we already did so in [scanReachableFiles]. |
- // Recording and reporting this twice is unnecessary, but we do so for now to |
- // validate that the results are consistent. |
- scanTimer = new Stopwatch(); |
- var old = scanTotalChars; |
- scanTotalChars = 0; |
- for (var source in files) { |
- tokenize(source); |
+/// Add to [files] all sources reachable from [start]. |
+void collectSources(Source start, Set<Source> files) { |
+ if (!files.add(start)) return; |
+ var unit = parseDirectives(start); |
+ for (var directive in unit.directives) { |
+ if (directive is UriBasedDirective) { |
+ var next = sources.resolveUri(start, directive.uri.stringValue); |
+ collectSources(next, files); |
+ } |
} |
+} |
- // Report size and scanning time again. See discussion above. |
- if (old != scanTotalChars) print('input size changed? ${old} chars'); |
- report("scan", scanTimer.elapsedMicroseconds); |
+Future<Program> generateKernel(Uri entryUri, |
+ {bool useSdkSummary: false, bool compileSdk: true}) async { |
+ var dartkTimer = new Stopwatch()..start(); |
+ // TODO(sigmund): add a constructor with named args to compiler options. |
+ var options = new CompilerOptions() |
+ ..strongMode = false |
+ ..compileSdk = compileSdk |
+ ..packagesFilePath = '.packages' |
+ ..onError = ((e) => print('${e.message}')); |
+ if (useSdkSummary) { |
+ // TODO(sigmund): adjust path based on the benchmark runner architecture. |
+ // Possibly let the runner make the file available at an architecture |
+ // independent location. |
+ options.sdkSummary = 'out/ReleaseX64/dart-sdk/lib/_internal/spec.sum'; |
+ } else { |
+ options.sdkPath = 'sdk'; |
+ } |
+ Program program = await kernelForProgram(entryUri, options); |
+ dartkTimer.stop(); |
+ var suffix = useSdkSummary ? "_sum" : ""; |
+ report("kernel_gen_e2e${suffix}", dartkTimer.elapsedMicroseconds); |
+ return program; |
} |
-/// Parses every file in [files] and reports the time spent doing so. |
-void parseFiles(Set<Source> files) { |
- // The code below will record again how many chars are scanned and how long it |
- // takes to scan them, even though we already did so in [scanReachableFiles]. |
- // Recording and reporting this twice is unnecessary, but we do so for now to |
- // validate that the results are consistent. |
- scanTimer = new Stopwatch(); |
- var old = scanTotalChars; |
- scanTotalChars = 0; |
- parseTimer = new Stopwatch(); |
+/// Generates unlinkmed summaries for all files in [files], and returns them in |
+/// an [UnlinkedSummaries] container. |
+UnlinkedSummaries generateUnlinkedSummaries(Set<Source> files) { |
+ var unlinkedSummaries = new UnlinkedSummaries(); |
for (var source in files) { |
- parseFull(source); |
+ unlinkedSummaries.summariesByUri[source.uri.toString()] = |
+ unlinkedSummarize(source); |
} |
- |
- // Report size and scanning time again. See discussion above. |
- if (old != scanTotalChars) print('input size changed? ${old} chars'); |
- report("scan", scanTimer.elapsedMicroseconds); |
- report("parse", parseTimer.elapsedMicroseconds); |
+ return unlinkedSummaries; |
} |
-/// Produces unlinked summaries for every file in [files] and reports the time |
+/// Produces linked summaries for every file in [files] and reports the time |
/// spent doing so. |
-void unlinkedSummarizeFiles(Set<Source> files) { |
+void linkedSummarizeFiles(Set<Source> files) { |
// The code below will record again how many chars are scanned and how long it |
// takes to scan them, even though we already did so in [scanReachableFiles]. |
// Recording and reporting this twice is unnecessary, but we do so for now to |
@@ -226,7 +185,21 @@ void unlinkedSummarizeFiles(Set<Source> files) { |
scanTotalChars = 0; |
parseTimer = new Stopwatch(); |
unlinkedSummarizeTimer = new Stopwatch(); |
- generateUnlinkedSummaries(files); |
+ var unlinkedSummaries = generateUnlinkedSummaries(files); |
+ prelinkSummaryTimer = new Stopwatch(); |
+ Map<String, LinkedLibraryBuilder> prelinkedLibraries = |
+ prelinkSummaries(files, unlinkedSummaries); |
+ var linkTimer = new Stopwatch()..start(); |
+ LinkedLibrary getDependency(String uri) { |
+ // getDependency should never be called because all dependencies are present |
+ // in [prelinkedLibraries]. |
+ print('Warning: getDependency called for: $uri'); |
+ return null; |
+ } |
+ |
+ bool strong = true; |
+ relink(prelinkedLibraries, getDependency, unlinkedSummaries.getUnit, strong); |
+ linkTimer.stop(); |
if (old != scanTotalChars) print('input size changed? ${old} chars'); |
report("scan", scanTimer.elapsedMicroseconds); |
@@ -236,37 +209,19 @@ void unlinkedSummarizeFiles(Set<Source> files) { |
'unlinked summarize + parse', |
unlinkedSummarizeTimer.elapsedMicroseconds + |
parseTimer.elapsedMicroseconds); |
+ report('prelink', prelinkSummaryTimer.elapsedMicroseconds); |
+ report('link', linkTimer.elapsedMicroseconds); |
} |
-/// Simple container for a mapping from URI string to an unlinked summary. |
-class UnlinkedSummaries { |
- final summariesByUri = <String, UnlinkedUnit>{}; |
- |
- /// Get the unlinked summary for the given URI, and report a warning if it |
- /// can't be found. |
- UnlinkedUnit getUnit(String uri) { |
- var result = summariesByUri[uri]; |
- if (result == null) { |
- print('Warning: no summary found for: $uri'); |
- } |
- return result; |
- } |
-} |
- |
-/// Generates unlinkmed summaries for all files in [files], and returns them in |
-/// an [UnlinkedSummaries] container. |
-UnlinkedSummaries generateUnlinkedSummaries(Set<Source> files) { |
- var unlinkedSummaries = new UnlinkedSummaries(); |
- for (var source in files) { |
- unlinkedSummaries.summariesByUri[source.uri.toString()] = |
- unlinkedSummarize(source); |
- } |
- return unlinkedSummaries; |
+/// Uses the diet-parser to parse only directives in [source]. |
+CompilationUnit parseDirectives(Source source) { |
+ var token = tokenize(source); |
+ var parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER); |
+ return parser.parseDirectives(token); |
} |
-/// Produces prelinked summaries for every file in [files] and reports the time |
-/// spent doing so. |
-void prelinkedSummarizeFiles(Set<Source> files) { |
+/// Parses every file in [files] and reports the time spent doing so. |
+void parseFiles(Set<Source> files) { |
// The code below will record again how many chars are scanned and how long it |
// takes to scan them, even though we already did so in [scanReachableFiles]. |
// Recording and reporting this twice is unnecessary, but we do so for now to |
@@ -275,25 +230,29 @@ void prelinkedSummarizeFiles(Set<Source> files) { |
var old = scanTotalChars; |
scanTotalChars = 0; |
parseTimer = new Stopwatch(); |
- unlinkedSummarizeTimer = new Stopwatch(); |
- var unlinkedSummaries = generateUnlinkedSummaries(files); |
- prelinkSummaryTimer = new Stopwatch(); |
- prelinkSummaries(files, unlinkedSummaries); |
+ for (var source in files) { |
+ parseFull(source); |
+ } |
+ // Report size and scanning time again. See discussion above. |
if (old != scanTotalChars) print('input size changed? ${old} chars'); |
report("scan", scanTimer.elapsedMicroseconds); |
report("parse", parseTimer.elapsedMicroseconds); |
- report('unlinked summarize', unlinkedSummarizeTimer.elapsedMicroseconds); |
- report( |
- 'unlinked summarize + parse', |
- unlinkedSummarizeTimer.elapsedMicroseconds + |
- parseTimer.elapsedMicroseconds); |
- report('prelink', prelinkSummaryTimer.elapsedMicroseconds); |
} |
-/// Produces linked summaries for every file in [files] and reports the time |
+/// Parse the full body of [source] and return it's compilation unit. |
+CompilationUnit parseFull(Source source) { |
+ var token = tokenize(source); |
+ parseTimer.start(); |
+ var parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER); |
+ var unit = parser.parseCompilationUnit(token); |
+ parseTimer.stop(); |
+ return unit; |
+} |
+ |
+/// Produces prelinked summaries for every file in [files] and reports the time |
/// spent doing so. |
-void linkedSummarizeFiles(Set<Source> files) { |
+void prelinkedSummarizeFiles(Set<Source> files) { |
// The code below will record again how many chars are scanned and how long it |
// takes to scan them, even though we already did so in [scanReachableFiles]. |
// Recording and reporting this twice is unnecessary, but we do so for now to |
@@ -305,19 +264,7 @@ void linkedSummarizeFiles(Set<Source> files) { |
unlinkedSummarizeTimer = new Stopwatch(); |
var unlinkedSummaries = generateUnlinkedSummaries(files); |
prelinkSummaryTimer = new Stopwatch(); |
- Map<String, LinkedLibraryBuilder> prelinkedLibraries = |
- prelinkSummaries(files, unlinkedSummaries); |
- var linkTimer = new Stopwatch()..start(); |
- LinkedLibrary getDependency(String uri) { |
- // getDependency should never be called because all dependencies are present |
- // in [prelinkedLibraries]. |
- print('Warning: getDependency called for: $uri'); |
- return null; |
- } |
- |
- bool strong = true; |
- relink(prelinkedLibraries, getDependency, unlinkedSummaries.getUnit, strong); |
- linkTimer.stop(); |
+ prelinkSummaries(files, unlinkedSummaries); |
if (old != scanTotalChars) print('input size changed? ${old} chars'); |
report("scan", scanTimer.elapsedMicroseconds); |
@@ -328,7 +275,6 @@ void linkedSummarizeFiles(Set<Source> files) { |
unlinkedSummarizeTimer.elapsedMicroseconds + |
parseTimer.elapsedMicroseconds); |
report('prelink', prelinkSummaryTimer.elapsedMicroseconds); |
- report('link', linkTimer.elapsedMicroseconds); |
} |
/// Prelinks all the summaries for [files], using [unlinkedSummaries] to obtain |
@@ -348,41 +294,79 @@ Map<String, LinkedLibraryBuilder> prelinkSummaries( |
return prelinkedLibraries; |
} |
-/// Add to [files] all sources reachable from [start]. |
-void collectSources(Source start, Set<Source> files) { |
- if (!files.add(start)) return; |
- var unit = parseDirectives(start); |
- for (var directive in unit.directives) { |
- if (directive is UriBasedDirective) { |
- var next = sources.resolveUri(start, directive.uri.stringValue); |
- collectSources(next, files); |
- } |
- } |
+/// Report that metric [name] took [time] micro-seconds to process |
+/// [scanTotalChars] characters. |
+void report(String name, int time) { |
+ var sb = new StringBuffer(); |
+ sb.write('$name: $time us, ${time ~/ 1000} ms'); |
+ sb.write(', ${scanTotalChars * 1000 ~/ time} chars/ms'); |
+ print('$sb'); |
} |
-/// Uses the diet-parser to parse only directives in [source]. |
-CompilationUnit parseDirectives(Source source) { |
- var token = tokenize(source); |
- var parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER); |
- return parser.parseDirectives(token); |
+/// Scans every file in [files] and reports the time spent doing so. |
+void scanFiles(Set<Source> files) { |
+ // The code below will record again how many chars are scanned and how long it |
+ // takes to scan them, even though we already did so in [scanReachableFiles]. |
+ // Recording and reporting this twice is unnecessary, but we do so for now to |
+ // validate that the results are consistent. |
+ scanTimer = new Stopwatch(); |
+ var old = scanTotalChars; |
+ scanTotalChars = 0; |
+ for (var source in files) { |
+ tokenize(source); |
+ } |
+ |
+ // Report size and scanning time again. See discussion above. |
+ if (old != scanTotalChars) print('input size changed? ${old} chars'); |
+ report("scan", scanTimer.elapsedMicroseconds); |
} |
-/// Parse the full body of [source] and return it's compilation unit. |
-CompilationUnit parseFull(Source source) { |
- var token = tokenize(source); |
- parseTimer.start(); |
- var parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER); |
- var unit = parser.parseCompilationUnit(token); |
- parseTimer.stop(); |
- return unit; |
+/// Load and scans all files we need to process: files reachable from the |
+/// entrypoint and all core libraries automatically included by the VM. |
+Set<Source> scanReachableFiles(Uri entryUri) { |
+ var files = new Set<Source>(); |
+ var loadTimer = new Stopwatch()..start(); |
+ collectSources(sources.forUri2(entryUri), files); |
+ |
+ var libs = [ |
+ "dart:async", |
+ "dart:collection", |
+ "dart:convert", |
+ "dart:core", |
+ "dart:developer", |
+ "dart:_internal", |
+ "dart:isolate", |
+ "dart:math", |
+ "dart:mirrors", |
+ "dart:typed_data", |
+ "dart:io" |
+ ]; |
+ |
+ for (var lib in libs) { |
+ collectSources(sources.forUri(lib), files); |
+ } |
+ |
+ loadTimer.stop(); |
+ |
+ print('input size: ${scanTotalChars} chars'); |
+ var loadTime = loadTimer.elapsedMicroseconds - scanTimer.elapsedMicroseconds; |
+ report("load", loadTime); |
+ report("scan", scanTimer.elapsedMicroseconds); |
+ return files; |
} |
-UnlinkedUnitBuilder unlinkedSummarize(Source source) { |
- var unit = parseFull(source); |
- unlinkedSummarizeTimer.start(); |
- var unlinkedUnit = serializeAstUnlinked(unit); |
- unlinkedSummarizeTimer.stop(); |
- return unlinkedUnit; |
+/// Sets up analyzer to be able to load and resolve app, packages, and sdk |
+/// sources. |
+Future setup(Uri entryUri) async { |
+ var provider = PhysicalResourceProvider.INSTANCE; |
+ var packageMap = new ContextBuilder(provider, null, null) |
+ .convertPackagesToMap(await findPackages(entryUri)); |
+ sources = new SourceFactory([ |
+ new ResourceUriResolver(provider), |
+ new PackageMapUriResolver(provider, packageMap), |
+ new DartUriResolver( |
+ new FolderBasedDartSdk(provider, provider.getFolder("sdk"))), |
+ ]); |
} |
/// Scan [source] and return the first token produced by the scanner. |
@@ -398,6 +382,53 @@ Token tokenize(Source source) { |
return token; |
} |
+UnlinkedUnitBuilder unlinkedSummarize(Source source) { |
+ var unit = parseFull(source); |
+ unlinkedSummarizeTimer.start(); |
+ var unlinkedUnit = serializeAstUnlinked(unit); |
+ unlinkedSummarizeTimer.stop(); |
+ return unlinkedUnit; |
+} |
+ |
+/// Produces unlinked summaries for every file in [files] and reports the time |
+/// spent doing so. |
+void unlinkedSummarizeFiles(Set<Source> files) { |
+ // The code below will record again how many chars are scanned and how long it |
+ // takes to scan them, even though we already did so in [scanReachableFiles]. |
+ // Recording and reporting this twice is unnecessary, but we do so for now to |
+ // validate that the results are consistent. |
+ scanTimer = new Stopwatch(); |
+ var old = scanTotalChars; |
+ scanTotalChars = 0; |
+ parseTimer = new Stopwatch(); |
+ unlinkedSummarizeTimer = new Stopwatch(); |
+ generateUnlinkedSummaries(files); |
+ |
+ if (old != scanTotalChars) print('input size changed? ${old} chars'); |
+ report("scan", scanTimer.elapsedMicroseconds); |
+ report("parse", parseTimer.elapsedMicroseconds); |
+ report('unlinked summarize', unlinkedSummarizeTimer.elapsedMicroseconds); |
+ report( |
+ 'unlinked summarize + parse', |
+ unlinkedSummarizeTimer.elapsedMicroseconds + |
+ parseTimer.elapsedMicroseconds); |
+} |
+ |
+/// Simple container for a mapping from URI string to an unlinked summary. |
+class UnlinkedSummaries { |
+ final summariesByUri = <String, UnlinkedUnit>{}; |
+ |
+ /// Get the unlinked summary for the given URI, and report a warning if it |
+ /// can't be found. |
+ UnlinkedUnit getUnit(String uri) { |
+ var result = summariesByUri[uri]; |
+ if (result == null) { |
+ print('Warning: no summary found for: $uri'); |
+ } |
+ return result; |
+ } |
+} |
+ |
class _Scanner extends Scanner { |
_Scanner(String contents) : super(new CharSequenceReader(contents)) { |
preserveComments = false; |
@@ -408,36 +439,3 @@ class _Scanner extends Scanner { |
// ignore errors. |
} |
} |
- |
-/// Report that metric [name] took [time] micro-seconds to process |
-/// [scanTotalChars] characters. |
-void report(String name, int time) { |
- var sb = new StringBuffer(); |
- sb.write('$name: $time us, ${time ~/ 1000} ms'); |
- sb.write(', ${scanTotalChars * 1000 ~/ time} chars/ms'); |
- print('$sb'); |
-} |
- |
-Future<Program> generateKernel(Uri entryUri, |
- {bool useSdkSummary: false, bool compileSdk: true}) async { |
- var dartkTimer = new Stopwatch()..start(); |
- // TODO(sigmund): add a constructor with named args to compiler options. |
- var options = new CompilerOptions() |
- ..strongMode = false |
- ..compileSdk = compileSdk |
- ..packagesFilePath = '.packages' |
- ..onError = ((e) => print('${e.message}')); |
- if (useSdkSummary) { |
- // TODO(sigmund): adjust path based on the benchmark runner architecture. |
- // Possibly let the runner make the file available at an architecture |
- // independent location. |
- options.sdkSummary = 'out/ReleaseX64/dart-sdk/lib/_internal/spec.sum'; |
- } else { |
- options.sdkPath = 'sdk'; |
- } |
- Program program = await kernelForProgram(entryUri, options); |
- dartkTimer.stop(); |
- var suffix = useSdkSummary ? "_sum" : ""; |
- report("kernel_gen_e2e${suffix}", dartkTimer.elapsedMicroseconds); |
- return program; |
-} |