| 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 |