blob: c049cabbeca677b035212cf0f58ff730511af428 [file] [log] [blame] [edit]
// 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:dart_style/dart_style.dart';
import 'package:dart_style/src/constants.dart';
import 'package:path/path.dart' as p;
const _totalTrials = 100;
const _formatsPerTrial = 10;
final _benchmarkDirectory = p.dirname(p.fromUri(Platform.script));
void main(List<String> args) {
args = args.toList();
var isShort = args.remove('--short');
var benchmarkPath = '';
switch (args) {
case []:
// Default to the large benchmark.
benchmarkPath = p.join(_benchmarkDirectory, 'case/large.unit');
case [var path]:
benchmarkPath = path;
default:
stderr.writeln('Usage: benchmark/run.dart [--short] <path to benchmark>');
exit(64);
}
var sourceLines = File(benchmarkPath).readAsLinesSync();
// The first line may have a "|" to indicate the page width.
var pageWidth = 80;
if (sourceLines[0].endsWith('|')) {
pageWidth = sourceLines[0].indexOf('|');
sourceLines.removeAt(0);
}
var source = sourceLines.join('\n');
var expected =
File(p.setExtension(benchmarkPath, isShort ? '.expect_short' : '.expect'))
.readAsStringSync();
var benchmarkName = p.basenameWithoutExtension(benchmarkPath);
var formatter = DartFormatter(
pageWidth: pageWidth,
experimentFlags: [if (!isShort) tallStyleExperimentFlag]);
var isStatement = benchmarkPath.endsWith('.stmt');
print('Benchmarking "$benchmarkName" '
'using ${isShort ? 'short' : 'tall'} style...');
// Run the benchmark several times. This ensures the VM is warmed up and lets
// us see how much variance there is.
var best = 99999999.0;
for (var i = 0; i <= _totalTrials; i++) {
var stopwatch = Stopwatch()..start();
// For a single benchmark, format the source multiple times.
String? result;
for (var j = 0; j < _formatsPerTrial; j++) {
if (isStatement) {
result = formatter.formatStatement(source);
} else {
result = formatter.format(source);
}
}
var elapsed = stopwatch.elapsedMilliseconds / _formatsPerTrial;
// Keep track of the best run so far.
if (elapsed >= best) continue;
best = elapsed;
// Sanity check to make sure the output is what we expect and to make sure
// the VM doesn't optimize "dead" code away.
if (result != expected) {
print('Incorrect output:\n$result');
exit(1);
}
// Don't print the first run. It's always terrible since the VM hasn't
// warmed up yet.
if (i == 0) continue;
_printResult("Run ${'#$i'.padLeft(4)}", elapsed);
}
_printResult('Best ', best);
}
void _printResult(String label, double time) {
print('$label: ${time.toStringAsFixed(2).padLeft(6)}ms '
"${'=' * ((time * 5).toInt())}");
}