| // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| import 'dart:async'; |
| import 'dart:io'; |
| |
| import 'package:benchmark_harness/benchmark_harness.dart'; |
| |
| import '../bin/collect_coverage.dart' as collect_coverage; |
| import '../bin/format_coverage.dart' as format_coverage; |
| |
| // Runs a test script with various different coverage configurations. |
| class CoverageBenchmark extends AsyncBenchmarkBase { |
| CoverageBenchmark( |
| ScoreEmitter emitter, |
| super.name, |
| this.script, { |
| this.gatherCoverage = false, |
| this.functionCoverage = false, |
| this.branchCoverage = false, |
| }) : super(emitter: emitter); |
| |
| final String script; |
| final bool gatherCoverage; |
| final bool functionCoverage; |
| final bool branchCoverage; |
| int iteration = 0; |
| |
| @override |
| Future<void> run() async { |
| print('Running $name...'); |
| final covFile = 'data/$name $iteration coverage.json'; |
| final lcovFile = 'data/$name $iteration lcov.info'; |
| ++iteration; |
| |
| await Process.start( |
| Platform.executable, |
| [ |
| if (branchCoverage) '--branch-coverage', |
| 'run', |
| if (gatherCoverage) ...[ |
| '--pause-isolates-on-exit', |
| '--disable-service-auth-codes', |
| '--enable-vm-service=1234', |
| ], |
| script, |
| ], |
| mode: ProcessStartMode.detached, |
| ); |
| if (gatherCoverage) { |
| await collect_coverage.main([ |
| '--wait-paused', |
| '--resume-isolates', |
| '--uri=http://127.0.0.1:1234/', |
| if (branchCoverage) '--branch-coverage', |
| if (functionCoverage) '--function-coverage', |
| '-o', |
| covFile, |
| ]); |
| |
| await format_coverage.main([ |
| '--lcov', |
| '--check-ignore', |
| '-i', |
| covFile, |
| '-o', |
| lcovFile, |
| ]); |
| } |
| } |
| } |
| |
| // Emitter that just captures the value. |
| class CaptureEmitter implements ScoreEmitter { |
| late double capturedValue; |
| |
| @override |
| void emit(String testName, double value) { |
| capturedValue = value; |
| } |
| } |
| |
| // Prints a JSON representation of the benchmark results, in a format compatible |
| // with the github benchmark action. |
| class JsonEmitter implements ScoreEmitter { |
| JsonEmitter(this._baseline); |
| |
| final double _baseline; |
| final _results = <String, double>{}; |
| |
| @override |
| void emit(String testName, double value) { |
| _results[testName] = value; |
| } |
| |
| String write() => '[${_results.entries.map((entry) => """{ |
| "name": "${entry.key}", |
| "unit": "times slower", |
| "value": ${(entry.value / _baseline).toStringAsFixed(2)} |
| }""").join(',\n')}]'; |
| } |
| |
| Future<void> runBenchmark(CoverageBenchmark benchmark) async { |
| for (var i = 0; i < 3; ++i) { |
| try { |
| await benchmark.report().timeout(const Duration(minutes: 2)); |
| return; |
| } on TimeoutException { |
| print('Timed out'); |
| } |
| } |
| print('Timed out too many times. Giving up.'); |
| exit(127); |
| } |
| |
| Future<String> runBenchmarkSet(String name, String script) async { |
| final captureEmitter = CaptureEmitter(); |
| await runBenchmark( |
| CoverageBenchmark(captureEmitter, '$name - no coverage', script)); |
| final benchmarkBaseline = captureEmitter.capturedValue; |
| |
| final emitter = JsonEmitter(benchmarkBaseline); |
| await runBenchmark(CoverageBenchmark( |
| emitter, '$name - basic coverage', script, |
| gatherCoverage: true)); |
| await runBenchmark(CoverageBenchmark( |
| emitter, '$name - function coverage', script, |
| gatherCoverage: true, functionCoverage: true)); |
| await runBenchmark(CoverageBenchmark( |
| emitter, '$name - branch coverage', script, |
| gatherCoverage: true, branchCoverage: true)); |
| return emitter.write(); |
| } |
| |
| Future<void> main() async { |
| // Assume this script was started from the root coverage directory. Change to |
| // the benchmark directory. |
| Directory.current = 'benchmark'; |
| final result = await runBenchmarkSet('Many isolates', 'many_isolates.dart'); |
| await File('data/benchmark_result.json').writeAsString(result); |
| exit(0); |
| } |