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

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

Issue 2385893002: Create entrypoint to measure performance of the dart2js frontend (Closed)
Patch Set: Cl comments 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:async';
9 import 'dart:io';
10
11 import 'package:compiler/compiler_new.dart';
12 import 'package:compiler/src/common.dart';
13 import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
14 import 'package:compiler/src/diagnostics/messages.dart'
15 show Message, MessageTemplate;
16 import 'package:compiler/src/io/source_file.dart';
17 import 'package:compiler/src/options.dart' show ParserOptions;
18 import 'package:compiler/src/options.dart';
19 import 'package:compiler/src/parser/element_listener.dart' show ScannerOptions;
20 import 'package:compiler/src/parser/listener.dart';
21 import 'package:compiler/src/parser/node_listener.dart' show NodeListener;
22 import 'package:compiler/src/parser/parser.dart' show Parser;
23 import 'package:compiler/src/parser/partial_parser.dart';
24 import 'package:compiler/src/platform_configuration.dart' as platform;
25 import 'package:compiler/src/scanner/scanner.dart';
26 import 'package:compiler/src/source_file_provider.dart';
27 import 'package:compiler/src/tokens/token.dart' show Token;
28 import 'package:package_config/discovery.dart' show findPackages;
29 import 'package:package_config/packages.dart' show Packages;
30 import 'package:package_config/src/util.dart' show checkValidPackageUri;
31
32 /// Cumulative total number of chars scanned.
33 int scanTotalChars = 0;
34
35 /// Cumulative time spent scanning.
36 Stopwatch scanTimer = new Stopwatch();
37
38 /// Helper class used to load source files using dart2js's internal APIs.
39 _Loader loader;
40
41 main(List<String> args) async {
42 // TODO(sigmund): provide sdk folder as well.
43 if (args.length < 2) {
44 print('usage: perf.dart <bench-id> <entry.dart>');
45 exit(1);
46 }
47 var totalTimer = new Stopwatch()..start();
48
49 var bench = args[0];
50 var entryUri = Uri.base.resolve(args[1]);
51
52 await setup(entryUri);
53
54 if (bench == 'scan') {
55 Set<SourceFile> files = await scanReachableFiles(entryUri);
56 // TODO(sigmund): consider replacing the warmup with instrumented snapshots.
57 for (int i = 0; i < 10; i++) scanFiles(files);
58 } else if (bench == 'parse') {
59 Set<SourceFile> files = await scanReachableFiles(entryUri);
60 // TODO(sigmund): consider replacing the warmup with instrumented snapshots.
61 for (int i = 0; i < 10; i++) parseFiles(files);
62 } else {
63 print('unsupported bench-id: $bench. Please specify "scan" or "parse"');
64 // TODO(sigmund): implement the remaining benchmarks.
65 exit(1);
66 }
67
68 totalTimer.stop();
69 report("total", totalTimer.elapsedMicroseconds);
70 }
71
72 Future setup(Uri entryUri) async {
73 var inputProvider = new CompilerSourceFileProvider();
74 var sdkLibraries = await platform.load(_platformConfigUri, inputProvider);
75 var packages = await findPackages(entryUri);
76 loader = new _Loader(inputProvider, sdkLibraries, packages);
77 }
78
79 /// Load and scans all files we need to process: files reachable from the
80 /// entrypoint and all core libraries automatically included by the VM.
81 Future<Set<SourceFile>> scanReachableFiles(Uri entryUri) async {
82 var files = new Set<SourceFile>();
83 var loadTimer = new Stopwatch()..start();
84 var entrypoints = [
85 entryUri,
86 Uri.parse("dart:async"),
87 Uri.parse("dart:collection"),
88 Uri.parse("dart:convert"),
89 Uri.parse("dart:core"),
90 Uri.parse("dart:developer"),
91 Uri.parse("dart:_internal"),
92 Uri.parse("dart:io"),
93 Uri.parse("dart:isolate"),
94 Uri.parse("dart:math"),
95 Uri.parse("dart:mirrors"),
96 Uri.parse("dart:typed_data"),
97 ];
98 for (var entry in entrypoints) {
99 await collectSources(await loader.loadFile(entry), files);
100 }
101 loadTimer.stop();
102
103 print('input size: ${scanTotalChars} chars');
104 var loadTime = loadTimer.elapsedMicroseconds - scanTimer.elapsedMicroseconds;
105 report("load", loadTime);
106 report("scan", scanTimer.elapsedMicroseconds);
107 return files;
108 }
109
110 /// Scans every file in [files] and reports the time spent doing so.
111 void scanFiles(Set<SourceFile> files) {
112 // The code below will record again how many chars are scanned and how long it
113 // takes to scan them, even though we already did so in [scanReachableFiles].
114 // Recording and reporting this twice is unnecessary, but we do so for now to
115 // validate that the results are consistent.
116 scanTimer = new Stopwatch();
117 var old = scanTotalChars;
118 scanTotalChars = 0;
119 for (var source in files) {
120 tokenize(source);
121 }
122
123 // Report size and scanning time again. See discussion above.
124 if (old != scanTotalChars) print('input size changed? ${old} chars');
125 report("scan", scanTimer.elapsedMicroseconds);
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
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 report(
148 "parse", parseTimer.elapsedMicroseconds - scanTimer.elapsedMicroseconds);
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 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 return listener.popNode();
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 Packages packages;
278
279 _Loader(this.inputProvider, this.sdkLibraries, this.packages);
280
281 Future<SourceFile> loadFile(Uri uri) async {
282 if (!uri.isAbsolute) throw 'Relative uri $uri provided to readScript.';
283 Uri resourceUri = _translateUri(uri);
284 if (resourceUri == null || resourceUri.scheme == 'dart-ext') {
285 throw '$uri not resolved or unsupported.';
286 }
287 var file = _cache[resourceUri];
288 if (file != null) return _cache[resourceUri];
289 return _cache[resourceUri] = await _readFile(resourceUri);
290 }
291
292 Future<SourceFile> _readFile(Uri uri) async {
293 var data = await inputProvider.readFromUri(uri);
294 if (data is List<int>) return new Utf8BytesSourceFile(uri, data);
295 if (data is String) return new StringSourceFile.fromUri(uri, data);
296 // TODO(sigmund): properly handle errors, just report, return null, wrap
297 // above and continue...
298 throw "Expected a 'String' or a 'List<int>' from the input "
299 "provider, but got: ${data.runtimeType}.";
300 }
301
302 Uri _translateUri(Uri uri) {
303 if (uri.scheme == 'dart') return sdkLibraries[uri.path];
304 if (uri.scheme == 'package') return _translatePackageUri(uri);
305 return uri;
306 }
307
308 Uri _translatePackageUri(Uri uri) {
309 checkValidPackageUri(uri);
310 return packages.resolve(uri, notFound: (_) {
311 print('$uri not found');
312 });
313 }
314 }
315
316 class _ParserOptions implements ParserOptions {
317 const _ParserOptions();
318 bool get enableGenericMethodSyntax => true;
319 }
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