| 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, stderr; | 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/error/listener.dart'; | 12 import 'package:analyzer/error/listener.dart'; |
| 13 import 'package:analyzer/file_system/file_system.dart' show ResourceUriResolver; | 13 import 'package:analyzer/file_system/file_system.dart' show ResourceUriResolver; |
| 14 import 'package:analyzer/file_system/physical_file_system.dart' | 14 import 'package:analyzer/file_system/physical_file_system.dart' |
| 15 show PhysicalResourceProvider; | 15 show PhysicalResourceProvider; |
| 16 import 'package:analyzer/source/package_map_resolver.dart'; | 16 import 'package:analyzer/source/package_map_resolver.dart'; |
| 17 import 'package:analyzer/src/context/builder.dart'; | 17 import 'package:analyzer/src/context/builder.dart'; |
| 18 import 'package:analyzer/src/dart/sdk/sdk.dart' show FolderBasedDartSdk; | 18 import 'package:analyzer/src/dart/sdk/sdk.dart' show FolderBasedDartSdk; |
| 19 import 'package:analyzer/src/generated/parser.dart'; | 19 import 'package:analyzer/src/generated/parser.dart'; |
| 20 import 'package:analyzer/src/generated/source.dart'; | 20 import 'package:analyzer/src/generated/source.dart'; |
| 21 import 'package:analyzer/src/generated/source_io.dart'; | 21 import 'package:analyzer/src/generated/source_io.dart'; |
| 22 import 'package:analyzer/src/summary/format.dart'; |
| 23 import 'package:analyzer/src/summary/summarize_ast.dart'; |
| 22 import 'package:kernel/analyzer/loader.dart'; | 24 import 'package:kernel/analyzer/loader.dart'; |
| 23 import 'package:kernel/kernel.dart'; | 25 import 'package:kernel/kernel.dart'; |
| 24 import 'package:package_config/discovery.dart'; | 26 import 'package:package_config/discovery.dart'; |
| 25 | 27 |
| 26 import 'package:front_end/src/scanner/reader.dart'; | 28 import 'package:front_end/src/scanner/reader.dart'; |
| 27 import 'package:front_end/src/scanner/scanner.dart'; | 29 import 'package:front_end/src/scanner/scanner.dart'; |
| 28 import 'package:front_end/src/scanner/token.dart'; | 30 import 'package:front_end/src/scanner/token.dart'; |
| 29 | 31 |
| 30 /// Cumulative total number of chars scanned. | 32 /// Cumulative total number of chars scanned. |
| 31 int scanTotalChars = 0; | 33 int scanTotalChars = 0; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 62 }, | 64 }, |
| 63 'kernel_gen_e2e': () async { | 65 'kernel_gen_e2e': () async { |
| 64 // TODO(sigmund): remove. This is used to compute the input size, we | 66 // TODO(sigmund): remove. This is used to compute the input size, we |
| 65 // should extract input size from frontend instead. | 67 // should extract input size from frontend instead. |
| 66 scanReachableFiles(entryUri); | 68 scanReachableFiles(entryUri); |
| 67 // TODO(sigmund): replace this warmup. Note that for very large programs, | 69 // TODO(sigmund): replace this warmup. Note that for very large programs, |
| 68 // the GC pressure on the VM seems to make this worse with time (maybe we | 70 // the GC pressure on the VM seems to make this worse with time (maybe we |
| 69 // are leaking memory?). That's why we run it twice and not 10 times. | 71 // are leaking memory?). That's why we run it twice and not 10 times. |
| 70 for (int i = 0; i < 2; i++) await generateKernel(entryUri); | 72 for (int i = 0; i < 2; i++) await generateKernel(entryUri); |
| 71 }, | 73 }, |
| 74 'unlinked_summarize': () async { |
| 75 Set<Source> files = scanReachableFiles(entryUri); |
| 76 // TODO(sigmund): replace the warmup with instrumented snapshots. |
| 77 for (int i = 0; i < 10; i++) unlinkedSummarizeFiles(files); |
| 78 } |
| 72 }; | 79 }; |
| 73 | 80 |
| 74 var handler = handlers[bench]; | 81 var handler = handlers[bench]; |
| 75 if (handler == null) { | 82 if (handler == null) { |
| 76 // TODO(sigmund): implement the remaining benchmarks. | 83 // TODO(sigmund): implement the remaining benchmarks. |
| 77 print('unsupported bench-id: $bench. Please specify one of the following: ' | 84 print('unsupported bench-id: $bench. Please specify one of the following: ' |
| 78 '${handlers.keys.join(", ")}'); | 85 '${handlers.keys.join(", ")}'); |
| 79 exit(1); | 86 exit(1); |
| 80 } | 87 } |
| 81 await handler(); | 88 await handler(); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 parseTimer.stop(); | 173 parseTimer.stop(); |
| 167 | 174 |
| 168 // Report size and scanning time again. See discussion above. | 175 // Report size and scanning time again. See discussion above. |
| 169 if (old != scanTotalChars) print('input size changed? ${old} chars'); | 176 if (old != scanTotalChars) print('input size changed? ${old} chars'); |
| 170 report("scan", scanTimer.elapsedMicroseconds); | 177 report("scan", scanTimer.elapsedMicroseconds); |
| 171 | 178 |
| 172 var pTime = parseTimer.elapsedMicroseconds - scanTimer.elapsedMicroseconds; | 179 var pTime = parseTimer.elapsedMicroseconds - scanTimer.elapsedMicroseconds; |
| 173 report("parse", pTime); | 180 report("parse", pTime); |
| 174 } | 181 } |
| 175 | 182 |
| 183 /// Produces unlinked summaries for every file in [files] and reports the time |
| 184 /// spent doing so. |
| 185 void unlinkedSummarizeFiles(Set<Source> files) { |
| 186 // The code below will record again how many chars are scanned and how long it |
| 187 // takes to scan them, even though we already did so in [scanReachableFiles]. |
| 188 // Recording and reporting this twice is unnecessary, but we do so for now to |
| 189 // validate that the results are consistent. |
| 190 scanTimer = new Stopwatch(); |
| 191 var old = scanTotalChars; |
| 192 scanTotalChars = 0; |
| 193 var summarizeTimer = new Stopwatch()..start(); |
| 194 for (var source in files) { |
| 195 unlinkedSummarize(source); |
| 196 } |
| 197 summarizeTimer.stop(); |
| 198 |
| 199 if (old != scanTotalChars) print('input size changed? ${old} chars'); |
| 200 |
| 201 // TODO(paulberry): subtract out scan/parse time? |
| 202 var summarizeTime = summarizeTimer.elapsedMicroseconds; |
| 203 report('unlinked summarize', summarizeTime); |
| 204 } |
| 205 |
| 176 /// Add to [files] all sources reachable from [start]. | 206 /// Add to [files] all sources reachable from [start]. |
| 177 void collectSources(Source start, Set<Source> files) { | 207 void collectSources(Source start, Set<Source> files) { |
| 178 if (!files.add(start)) return; | 208 if (!files.add(start)) return; |
| 179 var unit = parseDirectives(start); | 209 var unit = parseDirectives(start); |
| 180 for (var directive in unit.directives) { | 210 for (var directive in unit.directives) { |
| 181 if (directive is UriBasedDirective) { | 211 if (directive is UriBasedDirective) { |
| 182 var next = sources.resolveUri(start, directive.uri.stringValue); | 212 var next = sources.resolveUri(start, directive.uri.stringValue); |
| 183 collectSources(next, files); | 213 collectSources(next, files); |
| 184 } | 214 } |
| 185 } | 215 } |
| 186 } | 216 } |
| 187 | 217 |
| 188 /// Uses the diet-parser to parse only directives in [source]. | 218 /// Uses the diet-parser to parse only directives in [source]. |
| 189 CompilationUnit parseDirectives(Source source) { | 219 CompilationUnit parseDirectives(Source source) { |
| 190 var token = tokenize(source); | 220 var token = tokenize(source); |
| 191 var parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER); | 221 var parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER); |
| 192 return parser.parseDirectives(token); | 222 return parser.parseDirectives(token); |
| 193 } | 223 } |
| 194 | 224 |
| 195 /// Parse the full body of [source] and return it's compilation unit. | 225 /// Parse the full body of [source] and return it's compilation unit. |
| 196 CompilationUnit parseFull(Source source) { | 226 CompilationUnit parseFull(Source source) { |
| 197 var token = tokenize(source); | 227 var token = tokenize(source); |
| 198 var parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER); | 228 var parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER); |
| 199 return parser.parseCompilationUnit(token); | 229 return parser.parseCompilationUnit(token); |
| 200 } | 230 } |
| 201 | 231 |
| 232 UnlinkedUnitBuilder unlinkedSummarize(Source source) { |
| 233 var unit = parseFull(source); |
| 234 return serializeAstUnlinked(unit); |
| 235 } |
| 236 |
| 202 /// Scan [source] and return the first token produced by the scanner. | 237 /// Scan [source] and return the first token produced by the scanner. |
| 203 Token tokenize(Source source) { | 238 Token tokenize(Source source) { |
| 204 scanTimer.start(); | 239 scanTimer.start(); |
| 205 var contents = source.contents.data; | 240 var contents = source.contents.data; |
| 206 scanTotalChars += contents.length; | 241 scanTotalChars += contents.length; |
| 207 // TODO(sigmund): is there a way to scan from a random-access-file without | 242 // TODO(sigmund): is there a way to scan from a random-access-file without |
| 208 // first converting to String? | 243 // first converting to String? |
| 209 var scanner = new _Scanner(contents); | 244 var scanner = new _Scanner(contents); |
| 210 var token = scanner.tokenize(); | 245 var token = scanner.tokenize(); |
| 211 scanTimer.stop(); | 246 scanTimer.stop(); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 const int errorLimit = 100; | 282 const int errorLimit = 100; |
| 248 stderr.writeln(errors.take(errorLimit).join('\n')); | 283 stderr.writeln(errors.take(errorLimit).join('\n')); |
| 249 if (errors.length > errorLimit) { | 284 if (errors.length > errorLimit) { |
| 250 stderr.writeln('[error] ${errors.length - errorLimit} errors not shown'); | 285 stderr.writeln('[error] ${errors.length - errorLimit} errors not shown'); |
| 251 } | 286 } |
| 252 } | 287 } |
| 253 dartkTimer.stop(); | 288 dartkTimer.stop(); |
| 254 report("kernel_gen_e2e", dartkTimer.elapsedMicroseconds); | 289 report("kernel_gen_e2e", dartkTimer.elapsedMicroseconds); |
| 255 return program; | 290 return program; |
| 256 } | 291 } |
| OLD | NEW |