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 analyzer and measure its performance. | 5 /// An entrypoint used to run portions of analyzer and measure its performance. |
6 library analyzer_cli.tool.perf; | 6 library analyzer_cli.tool.perf; |
7 | 7 |
8 import 'dart:async'; | |
8 import 'dart:io' show exit; | 9 import 'dart:io' show exit; |
9 | 10 |
10 import 'package:analyzer/dart/ast/ast.dart'; | 11 import 'package:analyzer/dart/ast/ast.dart'; |
11 import 'package:analyzer/dart/ast/token.dart'; | 12 import 'package:analyzer/dart/ast/token.dart'; |
12 import 'package:analyzer/error/listener.dart'; | 13 import 'package:analyzer/error/listener.dart'; |
13 import 'package:analyzer/file_system/file_system.dart' show ResourceUriResolver; | 14 import 'package:analyzer/file_system/file_system.dart' show ResourceUriResolver; |
14 import 'package:analyzer/file_system/physical_file_system.dart' | 15 import 'package:analyzer/file_system/physical_file_system.dart' |
15 show PhysicalResourceProvider; | 16 show PhysicalResourceProvider; |
16 import 'package:analyzer/source/package_map_resolver.dart'; | 17 import 'package:analyzer/source/package_map_resolver.dart'; |
17 import 'package:analyzer/src/context/builder.dart'; | 18 import 'package:analyzer/src/context/builder.dart'; |
18 import 'package:analyzer/src/dart/scanner/reader.dart'; | 19 import 'package:analyzer/src/dart/scanner/reader.dart'; |
19 import 'package:analyzer/src/dart/scanner/scanner.dart'; | 20 import 'package:analyzer/src/dart/scanner/scanner.dart'; |
20 import 'package:analyzer/src/dart/sdk/sdk.dart' show FolderBasedDartSdk; | 21 import 'package:analyzer/src/dart/sdk/sdk.dart' show FolderBasedDartSdk; |
21 import 'package:analyzer/src/generated/parser.dart'; | 22 import 'package:analyzer/src/generated/parser.dart'; |
22 import 'package:analyzer/src/generated/source.dart'; | 23 import 'package:analyzer/src/generated/source.dart'; |
23 import 'package:analyzer/src/generated/source_io.dart'; | 24 import 'package:analyzer/src/generated/source_io.dart'; |
24 import 'package:package_config/discovery.dart'; | 25 import 'package:package_config/discovery.dart'; |
25 | 26 |
26 /// Cummulative total number of chars scanned. | 27 /// Cummulative total number of chars scanned. |
27 int scanTotalChars = 0; | 28 int scanTotalChars = 0; |
28 | 29 |
29 /// Cummulative time spent scanning. | 30 /// Cummulative time spent scanning. |
30 Stopwatch scanTimer = new Stopwatch(); | 31 Stopwatch scanTimer = new Stopwatch(); |
31 | 32 |
32 /// Factory to load and resolve app, packages, and sdk sources. | 33 /// Factory to load and resolve app, packages, and sdk sources. |
33 SourceFactory sources; | 34 SourceFactory sources; |
34 | 35 |
35 main(args) { | 36 main(List<String> args) async { |
36 // TODO(sigmund): provide sdk folder as well. | 37 // TODO(sigmund): provide sdk folder as well. |
37 if (args.length < 3) { | 38 if (args.length < 2) { |
38 print('usage: perf.dart <bench-id> <package-root> <entry.dart>'); | 39 print('usage: perf.dart <bench-id> <entry.dart>'); |
Paul Berry
2016/10/10 19:20:40
Consider using the args package so that we can hav
Siggi Cherem (dart-lang)
2016/10/10 19:30:02
Let's see how this evolves, my hope is that we can
| |
39 exit(1); | 40 exit(1); |
40 } | 41 } |
41 var totalTimer = new Stopwatch()..start(); | 42 var totalTimer = new Stopwatch()..start(); |
42 | 43 |
43 var bench = args[0]; | 44 var bench = args[0]; |
44 var packageRoot = Uri.base.resolve(args[1]); | 45 var entryUri = Uri.base.resolve(args[1]); |
45 var entryUri = Uri.base.resolve(args[2]); | |
46 | 46 |
47 setup(packageRoot); | 47 await setup(entryUri); |
48 | |
48 if (bench == 'scan') { | 49 if (bench == 'scan') { |
49 scanReachableFiles(entryUri); | 50 Set<Source> files = scanReachableFiles(entryUri); |
51 // TODO(sigmund): consider replacing the warmup with instrumented snapshots. | |
52 for (int i = 0; i < 10; i++) scanFiles(files); | |
Paul Berry
2016/10/10 19:20:40
It looks like the way you're doing the warmup is t
Siggi Cherem (dart-lang)
2016/10/10 19:30:01
Sorry - it is not obvious to see how I'm using thi
Paul Berry
2016/10/10 20:39:38
Ah, ok. I didn't realize that. In which case wha
| |
50 } else if (bench == 'parse') { | 53 } else if (bench == 'parse') { |
51 Set<Source> files = scanReachableFiles(entryUri); | 54 Set<Source> files = scanReachableFiles(entryUri); |
52 parseFiles(files); | 55 // TODO(sigmund): consider replacing the warmup with instrumented snapshots. |
56 for (int i = 0; i < 10; i++) parseFiles(files); | |
Paul Berry
2016/10/10 19:20:40
Similar comment here.
Siggi Cherem (dart-lang)
2016/10/10 19:30:02
Similar here :)
| |
53 } else { | 57 } else { |
54 print('unsupported bench-id: $bench. Please specify "scan" or "parse"'); | 58 print('unsupported bench-id: $bench. Please specify "scan" or "parse"'); |
55 // TODO(sigmund): implement the remaining benchmarks. | 59 // TODO(sigmund): implement the remaining benchmarks. |
56 exit(1); | 60 exit(1); |
57 } | 61 } |
58 | 62 |
59 totalTimer.stop(); | 63 totalTimer.stop(); |
60 report("total", totalTimer.elapsedMicroseconds); | 64 report("total", totalTimer.elapsedMicroseconds); |
61 } | 65 } |
62 | 66 |
63 /// Sets up analyzer to be able to load and resolve app, packages, and sdk | 67 /// Sets up analyzer to be able to load and resolve app, packages, and sdk |
64 /// sources. | 68 /// sources. |
65 void setup(Uri packageRoot) { | 69 Future setup(Uri entryUri) async { |
66 var provider = PhysicalResourceProvider.INSTANCE; | 70 var provider = PhysicalResourceProvider.INSTANCE; |
67 var packageMap = new ContextBuilder(provider, null, null) | 71 var packageMap = new ContextBuilder(provider, null, null) |
68 .convertPackagesToMap(getPackagesDirectory(packageRoot)); | 72 .convertPackagesToMap(await findPackages(entryUri)); |
69 sources = new SourceFactory([ | 73 sources = new SourceFactory([ |
70 new ResourceUriResolver(provider), | 74 new ResourceUriResolver(provider), |
71 new PackageMapUriResolver(provider, packageMap), | 75 new PackageMapUriResolver(provider, packageMap), |
72 new DartUriResolver( | 76 new DartUriResolver( |
73 new FolderBasedDartSdk(provider, provider.getFolder("sdk"))), | 77 new FolderBasedDartSdk(provider, provider.getFolder("sdk"))), |
74 ]); | 78 ]); |
75 } | 79 } |
76 | 80 |
77 /// Load and scans all files we need to process: files reachable from the | 81 /// Load and scans all files we need to process: files reachable from the |
78 /// entrypoint and all core libraries automatically included by the VM. | 82 /// entrypoint and all core libraries automatically included by the VM. |
79 Set<Source> scanReachableFiles(Uri entryUri) { | 83 Set<Source> scanReachableFiles(Uri entryUri) { |
80 var files = new Set<Source>(); | 84 var files = new Set<Source>(); |
81 var loadTimer = new Stopwatch()..start(); | 85 var loadTimer = new Stopwatch()..start(); |
82 collectSources(sources.forUri2(entryUri), files); | 86 collectSources(sources.forUri2(entryUri), files); |
83 collectSources(sources.forUri("dart:async"), files); | 87 |
84 collectSources(sources.forUri("dart:collection"), files); | 88 var libs = [ |
85 collectSources(sources.forUri("dart:convert"), files); | 89 "dart:async", |
86 collectSources(sources.forUri("dart:core"), files); | 90 "dart:collection", |
87 collectSources(sources.forUri("dart:developer"), files); | 91 "dart:convert", |
88 collectSources(sources.forUri("dart:_internal"), files); | 92 "dart:core", |
89 collectSources(sources.forUri("dart:isolate"), files); | 93 "dart:developer", |
90 collectSources(sources.forUri("dart:math"), files); | 94 "dart:_internal", |
91 collectSources(sources.forUri("dart:mirrors"), files); | 95 "dart:isolate", |
92 collectSources(sources.forUri("dart:typed_data"), files); | 96 "dart:math", |
97 "dart:mirrors", | |
98 "dart:typed_data", | |
99 "dart:io" | |
100 ]; | |
101 | |
102 for (var lib in libs) { | |
103 collectSources(sources.forUri(lib), files); | |
104 } | |
105 | |
93 loadTimer.stop(); | 106 loadTimer.stop(); |
94 | 107 |
95 print('input size: ${scanTotalChars} chars'); | 108 print('input size: ${scanTotalChars} chars'); |
96 var loadTime = loadTimer.elapsedMicroseconds - scanTimer.elapsedMicroseconds; | 109 var loadTime = loadTimer.elapsedMicroseconds - scanTimer.elapsedMicroseconds; |
97 report("load", loadTime); | 110 report("load", loadTime); |
98 report("scan", scanTimer.elapsedMicroseconds); | 111 report("scan", scanTimer.elapsedMicroseconds); |
99 return files; | 112 return files; |
100 } | 113 } |
101 | 114 |
115 /// Scans every file in [files] and reports the time spent doing so. | |
116 void scanFiles(Set<Source> files) { | |
117 // The code below will record again how many chars are scanned and how long it | |
118 // takes to scan them, even though we already did so in [scanReachableFiles]. | |
119 // Recording and reporting this twice is unnecessary, but we do so for now to | |
120 // validate that the results are consistent. | |
121 scanTimer = new Stopwatch(); | |
122 var old = scanTotalChars; | |
123 scanTotalChars = 0; | |
124 for (var source in files) { | |
125 tokenize(source); | |
126 } | |
127 | |
128 // Report size and scanning time again. See discussion above. | |
129 if (old != scanTotalChars) print('input size changed? ${old} chars'); | |
130 report("scan", scanTimer.elapsedMicroseconds); | |
131 } | |
132 | |
102 /// Parses every file in [files] and reports the time spent doing so. | 133 /// Parses every file in [files] and reports the time spent doing so. |
103 void parseFiles(Set<Source> files) { | 134 void parseFiles(Set<Source> files) { |
104 // The code below will record again how many chars are scanned and how long it | 135 // The code below will record again how many chars are scanned and how long it |
105 // takes to scan them, even though we already did so in [scanReachableFiles]. | 136 // takes to scan them, even though we already did so in [scanReachableFiles]. |
106 // Recording and reporting this twice is unnecessary, but we do so for now to | 137 // Recording and reporting this twice is unnecessary, but we do so for now to |
107 // validate that the results are consistent. | 138 // validate that the results are consistent. |
108 scanTimer = new Stopwatch(); | 139 scanTimer = new Stopwatch(); |
109 var old = scanTotalChars; | 140 var old = scanTotalChars; |
110 scanTotalChars = 0; | 141 scanTotalChars = 0; |
111 var parseTimer = new Stopwatch()..start(); | 142 var parseTimer = new Stopwatch()..start(); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
163 } | 194 } |
164 | 195 |
165 /// Report that metric [name] took [time] micro-seconds to process | 196 /// Report that metric [name] took [time] micro-seconds to process |
166 /// [scanTotalChars] characters. | 197 /// [scanTotalChars] characters. |
167 void report(String name, int time) { | 198 void report(String name, int time) { |
168 var sb = new StringBuffer(); | 199 var sb = new StringBuffer(); |
169 sb.write('$name: $time us, ${time ~/ 1000} ms'); | 200 sb.write('$name: $time us, ${time ~/ 1000} ms'); |
170 sb.write(', ${scanTotalChars * 1000 ~/ time} chars/ms'); | 201 sb.write(', ${scanTotalChars * 1000 ~/ time} chars/ms'); |
171 print('$sb'); | 202 print('$sb'); |
172 } | 203 } |
OLD | NEW |