OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /// An entrypoint used to run portions of fasta and measure its performance. | 5 /// An entrypoint used to run portions of fasta and measure its performance. |
6 library front_end.tool.fasta_perf; | 6 library front_end.tool.fasta_perf; |
7 | 7 |
8 import 'dart:async'; | 8 import 'dart:async'; |
9 import 'dart:io'; | 9 import 'dart:io'; |
10 | 10 |
11 import 'package:analyzer/src/fasta/ast_builder.dart'; | 11 import 'package:analyzer/src/fasta/ast_builder.dart'; |
| 12 import 'package:front_end/front_end.dart'; |
12 import 'package:front_end/physical_file_system.dart'; | 13 import 'package:front_end/physical_file_system.dart'; |
13 import 'package:front_end/src/fasta/dill/dill_target.dart' show DillTarget; | |
14 import 'package:front_end/src/fasta/kernel/kernel_target.dart' | |
15 show KernelTarget; | |
16 import 'package:front_end/src/fasta/parser.dart'; | 14 import 'package:front_end/src/fasta/parser.dart'; |
17 import 'package:front_end/src/fasta/scanner.dart'; | 15 import 'package:front_end/src/fasta/scanner.dart'; |
18 import 'package:front_end/src/fasta/scanner/io.dart' show readBytesFromFileSync; | 16 import 'package:front_end/src/fasta/scanner/io.dart' show readBytesFromFileSync; |
19 import 'package:front_end/src/fasta/source/directive_listener.dart'; | 17 import 'package:front_end/src/fasta/source/directive_listener.dart'; |
20 import 'package:front_end/src/fasta/ticker.dart' show Ticker; | |
21 import 'package:front_end/src/fasta/translate_uri.dart' show TranslateUri; | 18 import 'package:front_end/src/fasta/translate_uri.dart' show TranslateUri; |
22 import 'package:front_end/src/fasta/translate_uri.dart'; | 19 import 'package:front_end/src/fasta/parser/native_support.dart' |
23 import 'package:front_end/src/fasta/parser/dart_vm_native.dart' | |
24 show skipNativeClause; | 20 show skipNativeClause; |
25 import 'package:kernel/target/targets.dart' show TargetFlags; | |
26 import 'package:kernel/target/vm_fasta.dart' show VmFastaTarget; | |
27 | 21 |
28 /// Cumulative total number of chars scanned. | 22 /// Cumulative total number of chars scanned. |
29 int inputSize = 0; | 23 int inputSize = 0; |
30 | 24 |
31 /// Cumulative time spent scanning. | 25 /// Cumulative time spent scanning. |
32 Stopwatch scanTimer = new Stopwatch(); | 26 Stopwatch scanTimer = new Stopwatch(); |
33 | 27 |
34 main(List<String> args) async { | 28 main(List<String> args) async { |
35 // TODO(sigmund): provide sdk folder as well. | 29 // TODO(sigmund): provide sdk folder as well. |
36 if (args.length < 2) { | 30 if (args.length < 2) { |
37 print('usage: fasta_perf.dart <bench-id> <entry.dart>'); | 31 print('usage: fasta_perf.dart <bench-id> <entry.dart>'); |
38 exit(1); | 32 exit(1); |
39 } | 33 } |
40 var bench = args[0]; | 34 var bench = args[0]; |
41 var entryUri = Uri.base.resolve(args[1]); | 35 var entryUri = Uri.base.resolve(args[1]); |
42 | 36 |
43 await setup(entryUri); | 37 await setup(entryUri); |
44 | 38 |
45 Map<Uri, List<int>> files = await scanReachableFiles(entryUri); | 39 Map<Uri, List<int>> files = await scanReachableFiles(entryUri); |
46 var handlers = { | 40 var handlers = { |
47 'scan': () async => scanFiles(files), | 41 'scan': () async => scanFiles(files), |
48 // TODO(sigmund): enable when we can run the ast-builder standalone. | 42 // TODO(sigmund): enable when we can run the ast-builder standalone. |
49 // 'parse': () async => parseFiles(files), | 43 // 'parse': () async => parseFiles(files), |
50 'kernel_gen_e2e': () async { | 44 'kernel_gen_e2e': () async { |
51 await generateKernel(entryUri); | 45 await generateKernel(entryUri); |
52 }, | 46 }, |
53 // TODO(sigmund): enable once we add a build step to create the | 47 'kernel_gen_e2e_sum': () async { |
54 // platform.dill files. | 48 await generateKernel(entryUri, compileSdk: false); |
55 // 'kernel_gen_e2e_sum': () async { | 49 }, |
56 // await generateKernel(entryUri, compileSdk: false); | |
57 // }, | |
58 }; | 50 }; |
59 | 51 |
60 var handler = handlers[bench]; | 52 var handler = handlers[bench]; |
61 if (handler == null) { | 53 if (handler == null) { |
62 // TODO(sigmund): implement the remaining benchmarks. | 54 // TODO(sigmund): implement the remaining benchmarks. |
63 print('unsupported bench-id: $bench. Please specify one of the following: ' | 55 print('unsupported bench-id: $bench. Please specify one of the following: ' |
64 '${handlers.keys.join(", ")}'); | 56 '${handlers.keys.join(", ")}'); |
65 exit(1); | 57 exit(1); |
66 } | 58 } |
67 | 59 |
68 // TODO(sigmund): replace the warmup with instrumented snapshots. | 60 // TODO(sigmund): replace the warmup with instrumented snapshots. |
69 int iterations = bench.contains('kernel_gen') ? 2 : 10; | 61 int iterations = bench.contains('kernel_gen') ? 2 : 10; |
70 for (int i = 0; i < iterations; i++) { | 62 for (int i = 0; i < iterations; i++) { |
71 var totalTimer = new Stopwatch()..start(); | 63 var totalTimer = new Stopwatch()..start(); |
72 print('== iteration $i'); | 64 print('== iteration $i'); |
73 await handler(); | 65 await handler(); |
74 totalTimer.stop(); | 66 totalTimer.stop(); |
75 report('total', totalTimer.elapsedMicroseconds); | 67 report('total', totalTimer.elapsedMicroseconds); |
76 } | 68 } |
77 } | 69 } |
78 | 70 |
| 71 // TODO(sigmund): use `perf.dart::_findSdkPath` here when fasta can patch the |
| 72 // sdk directly. |
| 73 Uri sdkRoot = |
| 74 Uri.base.resolve(Platform.resolvedExecutable).resolve('patched_sdk/'); |
| 75 |
79 /// Translates `dart:*` and `package:*` URIs to resolved URIs. | 76 /// Translates `dart:*` and `package:*` URIs to resolved URIs. |
80 TranslateUri uriResolver; | 77 TranslateUri uriResolver; |
81 | 78 |
82 /// Preliminary set up to be able to correctly resolve URIs on the given | 79 /// Preliminary set up to be able to correctly resolve URIs on the given |
83 /// program. | 80 /// program. |
84 Future setup(Uri entryUri) async { | 81 Future setup(Uri entryUri) async { |
85 // TODO(sigmund): use `perf.dart::_findSdkPath` here when fasta can patch the | |
86 // sdk directly. | |
87 var sdkRoot = | |
88 Uri.base.resolve(Platform.resolvedExecutable).resolve('patched_sdk/'); | |
89 uriResolver = await TranslateUri.parse(PhysicalFileSystem.instance, sdkRoot); | 82 uriResolver = await TranslateUri.parse(PhysicalFileSystem.instance, sdkRoot); |
90 } | 83 } |
91 | 84 |
92 /// Scan [contents] and return the first token produced by the scanner. | 85 /// Scan [contents] and return the first token produced by the scanner. |
93 Token tokenize(List<int> contents) { | 86 Token tokenize(List<int> contents) { |
94 scanTimer.start(); | 87 scanTimer.start(); |
95 var token = scan(contents).tokens; | 88 var token = scan(contents).tokens; |
96 scanTimer.stop(); | 89 scanTimer.stop(); |
97 return token; | 90 return token; |
98 } | 91 } |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 var listener = new DirectiveListenerWithNative(); | 158 var listener = new DirectiveListenerWithNative(); |
166 new TopLevelParser(listener).parseUnit(tokenize(contents)); | 159 new TopLevelParser(listener).parseUnit(tokenize(contents)); |
167 return new Set<String>() | 160 return new Set<String>() |
168 ..addAll(listener.imports.map((directive) => directive.uri)) | 161 ..addAll(listener.imports.map((directive) => directive.uri)) |
169 ..addAll(listener.exports.map((directive) => directive.uri)) | 162 ..addAll(listener.exports.map((directive) => directive.uri)) |
170 ..addAll(listener.parts); | 163 ..addAll(listener.parts); |
171 } | 164 } |
172 | 165 |
173 class DirectiveListenerWithNative extends DirectiveListener { | 166 class DirectiveListenerWithNative extends DirectiveListener { |
174 @override | 167 @override |
175 Token handleNativeClause(Token token) => skipNativeClause(token); | 168 Token handleNativeClause(Token token) => skipNativeClause(token, true); |
176 } | 169 } |
177 | 170 |
178 /// Parses every file in [files] and reports the time spent doing so. | 171 /// Parses every file in [files] and reports the time spent doing so. |
179 void parseFiles(Map<Uri, List<int>> files) { | 172 void parseFiles(Map<Uri, List<int>> files) { |
180 scanTimer = new Stopwatch(); | 173 scanTimer = new Stopwatch(); |
181 var parseTimer = new Stopwatch()..start(); | 174 var parseTimer = new Stopwatch()..start(); |
182 files.forEach((uri, source) { | 175 files.forEach((uri, source) { |
183 parseFull(uri, source); | 176 parseFull(uri, source); |
184 }); | 177 }); |
185 parseTimer.stop(); | 178 parseTimer.stop(); |
(...skipping 14 matching lines...) Expand all Loading... |
200 // bodies. So this listener is not feature complete. | 193 // bodies. So this listener is not feature complete. |
201 class _PartialAstBuilder extends AstBuilder { | 194 class _PartialAstBuilder extends AstBuilder { |
202 _PartialAstBuilder(Uri uri) : super(null, null, null, null, null, true, uri); | 195 _PartialAstBuilder(Uri uri) : super(null, null, null, null, null, true, uri); |
203 | 196 |
204 // Note: this method converts the body to kernel, so we skip that here. | 197 // Note: this method converts the body to kernel, so we skip that here. |
205 @override | 198 @override |
206 finishFunction(annotations, formals, asyncModifier, body) {} | 199 finishFunction(annotations, formals, asyncModifier, body) {} |
207 } | 200 } |
208 | 201 |
209 // Invoke the fasta kernel generator for the program starting in [entryUri] | 202 // Invoke the fasta kernel generator for the program starting in [entryUri] |
210 // TODO(sigmund): update to use the frontend api once fasta is being hit. | |
211 generateKernel(Uri entryUri, | 203 generateKernel(Uri entryUri, |
212 {bool compileSdk: true, bool strongMode: false}) async { | 204 {bool compileSdk: true, bool strongMode: false}) async { |
213 // TODO(sigmund): this is here only to compute the input size, | 205 // TODO(sigmund): this is here only to compute the input size, |
214 // we should extract the input size from the frontend instead. | 206 // we should extract the input size from the frontend instead. |
215 scanReachableFiles(entryUri); | 207 scanReachableFiles(entryUri); |
216 | 208 |
217 var timer = new Stopwatch()..start(); | 209 var timer = new Stopwatch()..start(); |
218 final Ticker ticker = new Ticker(); | 210 var options = new CompilerOptions() |
219 final DillTarget dillTarget = new DillTarget(ticker, uriResolver, | 211 ..sdkRoot = sdkRoot |
220 new VmFastaTarget(new TargetFlags(strongMode: strongMode))); | 212 ..chaseDependencies = true |
221 final KernelTarget kernelTarget = | 213 ..packagesFileUri = Uri.base.resolve('.packages') |
222 new KernelTarget(PhysicalFileSystem.instance, dillTarget, uriResolver); | 214 ..compileSdk = compileSdk; |
| 215 if (!compileSdk) { |
| 216 options.sdkSummary = sdkRoot.resolve('outline.dill'); |
| 217 } |
| 218 |
223 var entrypoints = [ | 219 var entrypoints = [ |
224 entryUri, | 220 entryUri, |
225 // These extra libraries are added to match the same set of libraries | 221 // These extra libraries are added to match the same set of libraries |
226 // scanned by default by the VM and the other benchmarks. | 222 // scanned by default by the VM and the other benchmarks. |
227 Uri.parse('dart:async'), | 223 Uri.parse('dart:async'), |
228 Uri.parse('dart:collection'), | 224 Uri.parse('dart:collection'), |
229 Uri.parse('dart:convert'), | 225 Uri.parse('dart:convert'), |
230 Uri.parse('dart:core'), | 226 Uri.parse('dart:core'), |
231 Uri.parse('dart:developer'), | 227 Uri.parse('dart:developer'), |
232 Uri.parse('dart:_internal'), | 228 Uri.parse('dart:_internal'), |
233 Uri.parse('dart:io'), | 229 Uri.parse('dart:io'), |
234 Uri.parse('dart:isolate'), | 230 Uri.parse('dart:isolate'), |
235 Uri.parse('dart:math'), | 231 Uri.parse('dart:math'), |
236 Uri.parse('dart:mirrors'), | 232 Uri.parse('dart:mirrors'), |
237 Uri.parse('dart:typed_data'), | 233 Uri.parse('dart:typed_data'), |
238 ]; | 234 ]; |
239 entrypoints.forEach(kernelTarget.read); | 235 var program = await kernelForBuildUnit(entrypoints, options); |
240 | 236 |
241 if (!compileSdk) { | |
242 dillTarget.read( | |
243 Uri.base.resolve(Platform.resolvedExecutable).resolve('platform.dill')); | |
244 } | |
245 await dillTarget.buildOutlines(); | |
246 await kernelTarget.buildOutlines(); | |
247 var program = await kernelTarget.buildProgram(); | |
248 if (kernelTarget.errors.isNotEmpty) { | |
249 throw kernelTarget.errors.first; | |
250 } | |
251 timer.stop(); | 237 timer.stop(); |
252 report('kernel_gen_e2e', timer.elapsedMicroseconds); | 238 var name = 'kernel_gen_e2e${compileSdk ? "" : "_sum"}'; |
| 239 report(name, timer.elapsedMicroseconds); |
253 return program; | 240 return program; |
254 } | 241 } |
255 | 242 |
256 /// Report that metric [name] took [time] micro-seconds to process | 243 /// Report that metric [name] took [time] micro-seconds to process |
257 /// [inputSize] characters. | 244 /// [inputSize] characters. |
258 void report(String name, int time) { | 245 void report(String name, int time) { |
259 var sb = new StringBuffer(); | 246 var sb = new StringBuffer(); |
260 var padding = ' ' * (20 - name.length); | 247 var padding = ' ' * (20 - name.length); |
261 sb.write('$name:$padding $time us, ${time ~/ 1000} ms'); | 248 sb.write('$name:$padding $time us, ${time ~/ 1000} ms'); |
262 var invSpeed = (time * 1000 / inputSize).toStringAsFixed(2); | 249 var invSpeed = (time * 1000 / inputSize).toStringAsFixed(2); |
263 sb.write(', $invSpeed ns/char'); | 250 sb.write(', $invSpeed ns/char'); |
264 print('$sb'); | 251 print('$sb'); |
265 } | 252 } |
OLD | NEW |