Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(370)

Side by Side Diff: pkg/compiler/tool/perf.dart

Issue 2385893002: Create entrypoint to measure performance of the dart2js frontend (Closed)
Patch Set: p1 Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | pkg/compiler/tool/perf_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 /// An entrypoint used to run portions of dart2js and measure its performance.
6 library compiler.tool.perf;
7
8 import 'dart:io' show exit;
Harry Terkelsen 2016/10/10 20:05:07 I remember we had some problems with exit and usin
Siggi Cherem (dart-lang) 2016/10/10 21:46:13 Seems to still be an issue, but in this case it's
9
10 import 'dart:async';
11 import 'dart:io';
Harry Terkelsen 2016/10/10 20:05:07 this makes the previous import redundant
Siggi Cherem (dart-lang) 2016/10/10 21:46:13 Done.
12
13 import 'package:compiler/src/diagnostics/messages.dart'
14 show Message, MessageTemplate;
15 import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
16 import 'package:compiler/src/io/source_file.dart';
17 import 'package:compiler/src/options.dart';
18 import 'package:compiler/src/platform_configuration.dart' as platform;
19 import 'package:compiler/src/source_file_provider.dart';
20 import 'package:package_config/discovery.dart' show findPackages;
21 import 'package:package_config/packages.dart' show Packages;
22 import 'package:package_config/src/util.dart' show checkValidPackageUri;
23
Harry Terkelsen 2016/10/10 20:05:07 sort these imports?
Siggi Cherem (dart-lang) 2016/10/10 21:46:12 Done.
24 import 'package:compiler/compiler_new.dart';
25 import 'package:compiler/src/common.dart';
26 import 'package:compiler/src/options.dart' show ParserOptions;
27 import 'package:compiler/src/tokens/token.dart' show Token;
28 import 'package:compiler/src/parser/element_listener.dart' show ScannerOptions;
29 import 'package:compiler/src/parser/listener.dart';
30 import 'package:compiler/src/parser/partial_parser.dart';
31 import 'package:compiler/src/scanner/scanner.dart';
32 import 'package:compiler/src/parser/node_listener.dart' show NodeListener;
33 import 'package:compiler/src/parser/parser.dart' show Parser;
34
35 /// Cummulative total number of chars scanned.
Harry Terkelsen 2016/10/10 20:05:07 Cumulative
Siggi Cherem (dart-lang) 2016/10/10 21:46:12 Done.
36 int scanTotalChars = 0;
37
38 /// Cummulative time spent scanning.
Harry Terkelsen 2016/10/10 20:05:07 same
Siggi Cherem (dart-lang) 2016/10/10 21:46:12 Done.
39 Stopwatch scanTimer = new Stopwatch();
40
41 /// Helper class used to load source files using dart2js's internal APIs.
42 _Loader loader;
43
44 main(List<String> args) async {
45 // TODO(sigmund): provide sdk folder as well.
46 if (args.length < 2) {
47 print('usage: perf.dart <bench-id> <entry.dart>');
48 exit(1);
49 }
50 var totalTimer = new Stopwatch()..start();
51
52 var bench = args[0];
53 var entryUri = Uri.base.resolve(args[1]);
54
55 await setup(entryUri);
56
57 if (bench == 'scan') {
58 Set<SourceFile> files = await scanReachableFiles(entryUri);
59 // TODO(sigmund): consider replacing the warmup with instrumented snapshots.
60 for (int i = 0; i < 10; i++) scanFiles(files);
61 } else if (bench == 'parse') {
62 Set<SourceFile> files = await scanReachableFiles(entryUri);
63 // TODO(sigmund): consider replacing the warmup with instrumented snapshots.
64 for (int i = 0; i < 10; i++) parseFiles(files);
65 } else {
66 print('unsupported bench-id: $bench. Please specify "scan" or "parse"');
67 // TODO(sigmund): implement the remaining benchmarks.
68 exit(1);
69 }
70
71 totalTimer.stop();
72 report("total", totalTimer.elapsedMicroseconds);
73 }
74
75 Future setup(Uri entryUri) async {
76 var inputProvider = new CompilerSourceFileProvider();
77 var sdkLibraries = await platform.load(_platformConfigUri, inputProvider);
78 var packages = await findPackages(entryUri);
79 loader = new _Loader(inputProvider, sdkLibraries, packages);
80 }
81
82 /// Load and scans all files we need to process: files reachable from the
83 /// entrypoint and all core libraries automatically included by the VM.
84 Future<Set<SourceFile>> scanReachableFiles(Uri entryUri) async {
85 var files = new Set<SourceFile>();
86 var loadTimer = new Stopwatch()..start();
87 var entrypoints = [
88 entryUri,
89 Uri.parse("dart:async"),
90 Uri.parse("dart:collection"),
91 Uri.parse("dart:convert"),
92 Uri.parse("dart:core"),
93 Uri.parse("dart:developer"),
94 Uri.parse("dart:_internal"),
95 Uri.parse("dart:io"),
96 Uri.parse("dart:isolate"),
97 Uri.parse("dart:math"),
98 Uri.parse("dart:mirrors"),
99 Uri.parse("dart:typed_data"),
100 ];
101 for (var entry in entrypoints) {
102 await collectSources(await loader.loadFile(entry), files);
103 }
104 loadTimer.stop();
105
106 print('input size: ${scanTotalChars} chars');
107 var loadTime = loadTimer.elapsedMicroseconds - scanTimer.elapsedMicroseconds;
108 report("load", loadTime);
109 report("scan", scanTimer.elapsedMicroseconds);
110 return files;
111 }
112
113 /// Scans every file in [files] and reports the time spent doing so.
114 void scanFiles(Set<SourceFile> files) {
115 scanTimer = new Stopwatch();
116 var old = scanTotalChars;
117 scanTotalChars = 0;
118 for (var source in files) {
119 tokenize(source);
120 }
121
122 // Report size and scanning time again. See discussion above.
Harry Terkelsen 2016/10/10 20:05:07 maybe "see discussion in parseFiles"?
Harry Terkelsen 2016/10/10 20:05:07 I don't see a comment discussing this?
Siggi Cherem (dart-lang) 2016/10/10 21:46:12 Acknowledged.
Siggi Cherem (dart-lang) 2016/10/10 21:46:12 good point - I added this later and the comment wa
123 if (old != scanTotalChars) print('input size changed? ${old} chars');
124 report("scan", scanTimer.elapsedMicroseconds);
125 }
126
127
128 /// Parses every file in [files] and reports the time spent doing so.
129 void parseFiles(Set<SourceFile> files) {
130 // The code below will record again how many chars are scanned and how long it
Harry Terkelsen 2016/10/10 20:05:07 move this comment to scanFiles?
Siggi Cherem (dart-lang) 2016/10/10 21:46:12 Done.
131 // takes to scan them, even though we already did so in [scanReachableFiles].
132 // Recording and reporting this twice is unnecessary, but we do so for now to
133 // validate that the results are consistent.
134 scanTimer = new Stopwatch();
135 var old = scanTotalChars;
136 scanTotalChars = 0;
137 var parseTimer = new Stopwatch()..start();
138 for (var source in files) {
139 parseFull(source);
140 }
141 parseTimer.stop();
142
143 // Report size and scanning time again. See discussion above.
144 if (old != scanTotalChars) print('input size changed? ${old} chars');
145 report("scan", scanTimer.elapsedMicroseconds);
146
147 var pTime = parseTimer.elapsedMicroseconds - scanTimer.elapsedMicroseconds;
Harry Terkelsen 2016/10/10 20:05:07 pTime -> parseTime?
Siggi Cherem (dart-lang) 2016/10/10 21:46:12 Done.
148 report("parse", pTime);
149 }
150
151 /// Add to [files] all sources reachable from [start].
152 Future collectSources(SourceFile start, Set<SourceFile> files) async {
153 if (!files.add(start)) return;
154 for (var directive in parseDirectives(start)) {
155 var next = await loader.loadFile(start.uri.resolve(directive));
156 await collectSources(next, files);
157 }
158 }
159
160 /// Uses the diet-parser to parse only directives in [source], returns the
161 /// URIs seen in import/export/part directives in the file.
162 Set<String> parseDirectives(SourceFile source) {
163 var tokens = tokenize(source);
164 var listener = new DirectiveListener();
165 new PartialParser(listener, const _ParserOptions()).parseUnit(tokens);
166 return listener.targets;
167 }
168
169 /// Parse the full body of [source].
170 void parseFull(SourceFile source) {
171 var tokens = tokenize(source);
172 NodeListener listener = new NodeListener(
173 const ScannerOptions(canUseNative: true), new FakeReporter(), null);
174 Parser parser = new Parser(listener, const _ParserOptions());
175 parser.parseUnit(tokens);
176 listener.popNode();
Harry Terkelsen 2016/10/10 20:05:07 why are you calling this?
Siggi Cherem (dart-lang) 2016/10/10 21:46:12 Ah - I meant to return the value (even though I do
177 }
178
179 /// Scan [source] and return the first token produced by the scanner.
180 Token tokenize(SourceFile source) {
181 scanTimer.start();
182 scanTotalChars += source.length;
183 var token = new Scanner(source).tokenize();
184 scanTimer.stop();
185 return token;
186 }
187
188 /// Report that metric [name] took [time] micro-seconds to process
189 /// [scanTotalChars] characters.
190 void report(String name, int time) {
191 var sb = new StringBuffer();
192 sb.write('$name: $time us, ${time ~/ 1000} ms');
193 sb.write(', ${scanTotalChars * 1000 ~/ time} chars/ms');
194 print('$sb');
195 }
196
197 /// Listener that parses out just the uri in imports, exports, and part
198 /// directives.
199 class DirectiveListener extends Listener {
200 Set<String> targets = new Set<String>();
201
202 bool inDirective = false;
203 void enterDirective() {
204 inDirective = true;
205 }
206
207 void exitDirective() {
208 inDirective = false;
209 }
210
211 void beginImport(Token importKeyword) => enterDirective();
212 void beginExport(Token token) => enterDirective();
213 void beginPart(Token token) => enterDirective();
214
215 void beginLiteralString(Token token) {
216 if (inDirective) {
217 var quotedString = token.value;
218 targets.add(quotedString.substring(1, quotedString.length - 1));
219 }
220 }
221
222 void endExport(Token exportKeyword, Token semicolon) => exitDirective();
223 void endImport(Token importKeyword, Token deferredKeyword, Token asKeyword,
224 Token semicolon) =>
225 exitDirective();
226 void endPart(Token partKeyword, Token semicolon) => exitDirective();
227 }
228
229 Uri _libraryRoot = Platform.script.resolve('../../../sdk/');
230 Uri _platformConfigUri = _libraryRoot.resolve("lib/dart_server.platform");
231
232 class FakeReporter extends DiagnosticReporter {
233 final hasReportedError = false;
234 final options = new FakeReporterOptions();
235
236 withCurrentElement(e, f) => f();
237 log(m) => print(m);
238 internalError(_, m) => print(m);
239 spanFromSpannable(_) => null;
240
241 void reportError(DiagnosticMessage message,
242 [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
243 print('error: ${message.message}');
244 }
245
246 void reportWarning(DiagnosticMessage message,
247 [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
248 print('warning: ${message.message}');
249 }
250
251 void reportHint(DiagnosticMessage message,
252 [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
253 print('hint: ${message.message}');
254 }
255
256 void reportInfo(_, __, [Map arguments = const {}]) {}
257
258 DiagnosticMessage createMessage(_, MessageKind kind,
259 [Map arguments = const {}]) {
260 MessageTemplate template = MessageTemplate.TEMPLATES[kind];
261 Message message = template.message(arguments, false);
262 return new DiagnosticMessage(null, null, message);
263 }
264 }
265
266 class FakeReporterOptions {
267 bool get suppressHints => false;
268 bool get hidePackageWarnings => false;
269 }
270
271 class _Loader {
272 CompilerInput inputProvider;
273
274 /// Maps dart-URIs to a known location in the sdk.
275 Map<String, Uri> sdkLibraries;
276 Map<Uri, SourceFile> _cache = {};
277 Map _debug = {};
Harry Terkelsen 2016/10/10 20:05:07 remove?
Siggi Cherem (dart-lang) 2016/10/10 21:46:12 Done.
278 Packages packages;
279
280 _Loader(this.inputProvider, this.sdkLibraries, this.packages);
281
282 Future<SourceFile> loadFile(Uri uri) async {
283 if (!uri.isAbsolute) throw 'Relative uri $uri provided to readScript.';
284 Uri resourceUri = _translateUri(uri);
285 if (resourceUri == null || resourceUri.scheme == 'dart-ext') {
286 throw '$uri not resolved or unsupported.';
287 }
288 var file = _cache[resourceUri];
Harry Terkelsen 2016/10/10 20:05:07 use putIfAbsent here
Siggi Cherem (dart-lang) 2016/10/10 21:46:13 Unfortunately I can't - the code that computes the
289 if (file != null) return _cache[resourceUri];
290 var r = _cache[resourceUri] = await _readFile(resourceUri);
291 _debug[resourceUri] = uri;
292 return r;
293 }
294
295 Future<SourceFile> _readFile(Uri uri) async {
296 var data = await inputProvider.readFromUri(uri);
297 if (data is List<int>) return new Utf8BytesSourceFile(uri, data);
298 if (data is String) return new StringSourceFile.fromUri(uri, data);
299 // TODO(sigmund): properly handle errors, just report, return null, wrap
300 // above and continue...
301 throw "Expected a 'String' or a 'List<int>' from the input "
302 "provider, but got: ${data.runtimeType}.";
303 }
304
305 Uri _translateUri(Uri uri) {
306 if (uri.scheme == 'dart') return sdkLibraries[uri.path];
307 if (uri.scheme == 'package') return _translatePackageUri(uri);
308 return uri;
309 }
310
311 Uri _translatePackageUri(Uri uri) {
312 checkValidPackageUri(uri);
313 return packages.resolve(uri, notFound: (_) {
314 print('$uri not found');
315 });
316 }
317 }
318
319 class _ParserOptions implements ParserOptions {
320 const _ParserOptions();
321 bool get enableGenericMethodSyntax => true;
322 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/tool/perf_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698