| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 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 | 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 front_end and measure its performance. | 5 /// An entrypoint used to run portions of front_end and measure its performance. |
| 6 library front_end.tool.perf; | 6 library front_end.tool.perf; |
| 7 | 7 |
| 8 import 'dart:async'; | 8 import 'dart:async'; |
| 9 import 'dart:io' show exit; | 9 import 'dart:io' show exit, stderr; |
| 10 | 10 |
| 11 import 'package:analyzer/dart/ast/ast.dart'; | 11 import 'package:analyzer/dart/ast/ast.dart'; |
| 12 import 'package:analyzer/dart/ast/token.dart'; | 12 import 'package:analyzer/dart/ast/token.dart'; |
| 13 import 'package:analyzer/error/listener.dart'; | 13 import 'package:analyzer/error/listener.dart'; |
| 14 import 'package:analyzer/file_system/file_system.dart' show ResourceUriResolver; | 14 import 'package:analyzer/file_system/file_system.dart' show ResourceUriResolver; |
| 15 import 'package:analyzer/file_system/physical_file_system.dart' | 15 import 'package:analyzer/file_system/physical_file_system.dart' |
| 16 show PhysicalResourceProvider; | 16 show PhysicalResourceProvider; |
| 17 import 'package:analyzer/source/package_map_resolver.dart'; | 17 import 'package:analyzer/source/package_map_resolver.dart'; |
| 18 import 'package:analyzer/src/context/builder.dart'; | 18 import 'package:analyzer/src/context/builder.dart'; |
| 19 import 'package:analyzer/src/dart/scanner/reader.dart'; | 19 import 'package:analyzer/src/dart/scanner/reader.dart'; |
| 20 import 'package:analyzer/src/dart/scanner/scanner.dart'; | 20 import 'package:analyzer/src/dart/scanner/scanner.dart'; |
| 21 import 'package:analyzer/src/dart/sdk/sdk.dart' show FolderBasedDartSdk; | 21 import 'package:analyzer/src/dart/sdk/sdk.dart' show FolderBasedDartSdk; |
| 22 import 'package:analyzer/src/generated/parser.dart'; | 22 import 'package:analyzer/src/generated/parser.dart'; |
| 23 import 'package:analyzer/src/generated/source.dart'; | 23 import 'package:analyzer/src/generated/source.dart'; |
| 24 import 'package:analyzer/src/generated/source_io.dart'; | 24 import 'package:analyzer/src/generated/source_io.dart'; |
| 25 import 'package:kernel/analyzer/loader.dart'; |
| 26 import 'package:kernel/kernel.dart'; |
| 25 import 'package:package_config/discovery.dart'; | 27 import 'package:package_config/discovery.dart'; |
| 26 | 28 |
| 27 /// Cumulative total number of chars scanned. | 29 /// Cumulative total number of chars scanned. |
| 28 int scanTotalChars = 0; | 30 int scanTotalChars = 0; |
| 29 | 31 |
| 30 /// Cumulative time spent scanning. | 32 /// Cumulative time spent scanning. |
| 31 Stopwatch scanTimer = new Stopwatch(); | 33 Stopwatch scanTimer = new Stopwatch(); |
| 32 | 34 |
| 33 /// Factory to load and resolve app, packages, and sdk sources. | 35 /// Factory to load and resolve app, packages, and sdk sources. |
| 34 SourceFactory sources; | 36 SourceFactory sources; |
| 35 | 37 |
| 36 main(List<String> args) async { | 38 main(List<String> args) async { |
| 37 // TODO(sigmund): provide sdk folder as well. | 39 // TODO(sigmund): provide sdk folder as well. |
| 38 if (args.length < 2) { | 40 if (args.length < 2) { |
| 39 print('usage: perf.dart <bench-id> <entry.dart>'); | 41 print('usage: perf.dart <bench-id> <entry.dart>'); |
| 40 exit(1); | 42 exit(1); |
| 41 } | 43 } |
| 42 var totalTimer = new Stopwatch()..start(); | 44 var totalTimer = new Stopwatch()..start(); |
| 43 | 45 |
| 44 var bench = args[0]; | 46 var bench = args[0]; |
| 45 var entryUri = Uri.base.resolve(args[1]); | 47 var entryUri = Uri.base.resolve(args[1]); |
| 46 | 48 |
| 47 await setup(entryUri); | 49 await setup(entryUri); |
| 48 | 50 |
| 49 if (bench == 'scan') { | 51 var handlers = { |
| 50 Set<Source> files = scanReachableFiles(entryUri); | 52 'scan': () async { |
| 51 // TODO(sigmund): consider replacing the warmup with instrumented snapshots. | 53 Set<SourceFile> files = scanReachableFiles(entryUri); |
| 52 for (int i = 0; i < 10; i++) scanFiles(files); | 54 // TODO(sigmund): replace the warmup with instrumented snapshots. |
| 53 } else if (bench == 'parse') { | 55 for (int i = 0; i < 10; i++) scanFiles(files); |
| 54 Set<Source> files = scanReachableFiles(entryUri); | 56 }, |
| 55 // TODO(sigmund): consider replacing the warmup with instrumented snapshots. | 57 'parse': () async { |
| 56 for (int i = 0; i < 10; i++) parseFiles(files); | 58 Set<SourceFile> files = scanReachableFiles(entryUri); |
| 57 } else { | 59 // TODO(sigmund): replace the warmup with instrumented snapshots. |
| 58 print('unsupported bench-id: $bench. Please specify "scan" or "parse"'); | 60 for (int i = 0; i < 10; i++) parseFiles(files); |
| 61 }, |
| 62 'kernel_gen_e2e': () async { |
| 63 // TODO(sigmund): remove. This is used to compute the input size, we |
| 64 // should extract input size from frontend instead. |
| 65 scanReachableFiles(entryUri); |
| 66 // TODO(sigmund): replace this warmup. Note that for very large programs, |
| 67 // the GC pressure on the VM seems to make this worse with time (maybe we |
| 68 // are leaking memory?). That's why we run it twice and not 10 times. |
| 69 for (int i = 0; i < 2; i++) await generateKernel(entryUri); |
| 70 }, |
| 71 }; |
| 72 |
| 73 var handler = handlers[bench]; |
| 74 if (handler == null) { |
| 59 // TODO(sigmund): implement the remaining benchmarks. | 75 // TODO(sigmund): implement the remaining benchmarks. |
| 76 print('unsupported bench-id: $bench. Please specify one of the following: ' |
| 77 '${handler.keys.join(", ")}'); |
| 60 exit(1); | 78 exit(1); |
| 61 } | 79 } |
| 80 await handler(); |
| 62 | 81 |
| 63 totalTimer.stop(); | 82 totalTimer.stop(); |
| 64 report("total", totalTimer.elapsedMicroseconds); | 83 report("total", totalTimer.elapsedMicroseconds); |
| 65 } | 84 } |
| 66 | 85 |
| 67 /// Sets up analyzer to be able to load and resolve app, packages, and sdk | 86 /// Sets up analyzer to be able to load and resolve app, packages, and sdk |
| 68 /// sources. | 87 /// sources. |
| 69 Future setup(Uri entryUri) async { | 88 Future setup(Uri entryUri) async { |
| 70 var provider = PhysicalResourceProvider.INSTANCE; | 89 var provider = PhysicalResourceProvider.INSTANCE; |
| 71 var packageMap = new ContextBuilder(provider, null, null) | 90 var packageMap = new ContextBuilder(provider, null, null) |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 } | 213 } |
| 195 | 214 |
| 196 /// Report that metric [name] took [time] micro-seconds to process | 215 /// Report that metric [name] took [time] micro-seconds to process |
| 197 /// [scanTotalChars] characters. | 216 /// [scanTotalChars] characters. |
| 198 void report(String name, int time) { | 217 void report(String name, int time) { |
| 199 var sb = new StringBuffer(); | 218 var sb = new StringBuffer(); |
| 200 sb.write('$name: $time us, ${time ~/ 1000} ms'); | 219 sb.write('$name: $time us, ${time ~/ 1000} ms'); |
| 201 sb.write(', ${scanTotalChars * 1000 ~/ time} chars/ms'); | 220 sb.write(', ${scanTotalChars * 1000 ~/ time} chars/ms'); |
| 202 print('$sb'); | 221 print('$sb'); |
| 203 } | 222 } |
| 223 |
| 224 // TODO(sigmund): replace this once kernel is produced by the frontend directly. |
| 225 Future<Program> generateKernel(Uri entryUri) async { |
| 226 var dartkTimer = new Stopwatch()..start(); |
| 227 var options = new DartOptions(strongMode: false, sdk: 'sdk'); |
| 228 var packages = |
| 229 await createPackages(options.packagePath, discoveryPath: entryUri.path); |
| 230 var repository = new Repository(); |
| 231 DartLoader loader = new DartLoader(repository, options, packages); |
| 232 |
| 233 Program program = loader.loadProgram(entryUri.path); |
| 234 List errors = loader.errors; |
| 235 if (errors.isNotEmpty) { |
| 236 const int errorLimit = 100; |
| 237 stderr.writeln(errors.take(errorLimit).join('\n')); |
| 238 if (errors.length > errorLimit) { |
| 239 stderr.writeln('[error] ${errors.length - errorLimit} errors not shown'); |
| 240 } |
| 241 } |
| 242 dartkTimer.stop(); |
| 243 report("kernel_gen_e2e", dartkTimer.elapsedMicroseconds); |
| 244 return program; |
| 245 } |
| OLD | NEW |