| // Copyright (c) 2024, 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:io'; |
| |
| import 'package:path/path.dart' as p; |
| |
| final class Benchmark { |
| /// Finds all of the benchmarks in the `benchmark/cases` directory, relative |
| /// to [packageDirectory]. |
| static List<Benchmark> findAll(String packageDirectory) { |
| var casesDirectory = Directory(p.join(packageDirectory, 'benchmark/case')); |
| |
| var benchmarks = [ |
| for (var entry in casesDirectory.listSync()) |
| if (p.extension(entry.path) case '.unit' || '.stmt') read(entry.path), |
| ]; |
| |
| benchmarks.sort((a, b) => a.name.compareTo(b.name)); |
| |
| return benchmarks; |
| } |
| |
| /// Reads the benchmark from [path]. |
| /// |
| /// This should point to a `.unit` or `.stmt` file that has a corresponding |
| /// `.expect` and `expect_short` file in the same directory with those |
| /// expectations. |
| static Benchmark read(String path) { |
| var inputLines = File(path).readAsLinesSync(); |
| |
| // The first line may have a "|" to indicate the page width. |
| var pageWidth = 80; |
| if (inputLines[0].endsWith('|')) { |
| pageWidth = inputLines[0].indexOf('|'); |
| inputLines.removeAt(0); |
| } |
| |
| var input = inputLines.join('\n'); |
| |
| var shortOutput = File( |
| p.setExtension(path, '.expect_short'), |
| ).readAsStringSync(); |
| var tallOutput = File(p.setExtension(path, '.expect')).readAsStringSync(); |
| |
| return Benchmark( |
| name: p.basenameWithoutExtension(path), |
| input: input, |
| pageWidth: pageWidth, |
| isCompilationUnit: p.extension(path) == '.unit', |
| shortOutput: shortOutput, |
| tallOutput: tallOutput, |
| ); |
| } |
| |
| /// The short display name of the benchmark. |
| final String name; |
| |
| /// The unformatted input. |
| final String input; |
| |
| /// The page width that the input should be formatted at. |
| final int pageWidth; |
| |
| /// Whether the benchmark's code is an entire compilation unit or a statement. |
| final bool isCompilationUnit; |
| |
| /// The expected formatted output using short style. |
| final String shortOutput; |
| |
| /// The expected formatted output using tall style. |
| final String tallOutput; |
| |
| Benchmark({ |
| required this.name, |
| required this.input, |
| required this.pageWidth, |
| required this.isCompilationUnit, |
| required this.shortOutput, |
| required this.tallOutput, |
| }); |
| } |
| |
| /// Compiles the currently running script to an AOT snapshot and then executes |
| /// it. |
| /// |
| /// This function never returns. When the AOT snapshot ends, this exits the |
| /// process. |
| Future<Never> rerunAsAot(List<String> arguments) async { |
| var script = Platform.script.toFilePath(); |
| var snapshotPath = p.join( |
| Directory.systemTemp.path, |
| p.setExtension(p.basename(script), '.aot'), |
| ); |
| |
| print('Creating AOT snapshot for $script...'); |
| var result = await Process.run('dart', [ |
| 'compile', |
| 'aot-snapshot', |
| '-o', |
| snapshotPath, |
| script, |
| ]); |
| stdout.write(result.stdout); |
| stderr.write(result.stderr); |
| if (result.exitCode != 0) { |
| stderr.writeln('Failed to create AOT snapshot.'); |
| exit(result.exitCode); |
| } |
| |
| print('Running AOT snapshot...'); |
| var process = await Process.start('dartaotruntime', [ |
| snapshotPath, |
| ...arguments, |
| ]); |
| await stdout.addStream(process.stdout); |
| await stderr.addStream(process.stderr); |
| |
| var exitCode = await process.exitCode; |
| |
| await File(snapshotPath).delete(); |
| exit(exitCode); |
| } |