blob: b934d96eecf1d2b35a18b1a7e63756acfdcc9e3a [file] [log] [blame]
// 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.
//
// Generates both the dart and dart2 version of this benchmark.
import 'dart:io';
import 'package:path/path.dart' as path;
const String benchmarkName = 'InstantiateTypeArgs';
/// How many classes/calls to create for the InstantiateOnce and
/// RepeatInstantiateOnce benchmarks.
const int instantiateOnceCount = 1000;
/// How many classes/calls to create for the InstantiateMany and
/// RepeatInstantiateMany benchmarks.
const int instantiateManyCount = 1000;
void generateBenchmarkClassesAndUtilities(IOSink output, {required bool nnbd}) {
output.writeln('''
// 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.
//
// This benchmark suite measures the overhead of instantiating type arguments,
// with a particular aim of measuring the overhead of the caching mechanism.
''');
if (!nnbd) {
output.writeln('''
// @dart=2.9"
''');
}
output.writeln('''
import 'package:benchmark_harness/benchmark_harness.dart';
void main() {
// Instantiates a series of types, each type instantiated with a single type.
const InstantiateOnce().report();
// Repeats the instantiations in InstantiateOnce, this time depending
// on the now-filled caches.
const RepeatInstantiateOnce().report();
// Instantiates a single type many times, each type being a new instantiation.
const InstantiateMany().report();
// Repeats the instantiations in InstantiateMany, this time depending on the
// now-filled cache.
const RepeatInstantiateMany().report();
}
class InstantiateOnce extends BenchmarkBase {
const InstantiateOnce() : super('$benchmarkName.InstantiateOnce');
// Only call run once, else the remaining runs will have the cached types.
@override
void exercise() => run();
@override
void run() {
instantiateOnce<B>();
}
}
class RepeatInstantiateOnce extends BenchmarkBase {
const RepeatInstantiateOnce()
: super('$benchmarkName.RepeatInstantiateOnce');
@override
void setup() {
// Run once to make sure the instantiations are cached, in case this
// benchmark is run on its own.
instantiateOnce<B>();
}
// Only call run once, so this is directly comparable to InstantiateOnce.
@override
void exercise() => run();
@override
void run() {
instantiateOnce<B>();
}
}
class InstantiateMany extends BenchmarkBase {
const InstantiateMany() : super('$benchmarkName.InstantiateMany');
// Only call run once, else the remaining runs will have the cached types.
@override
void exercise() => run();
@override
void run() {
instantiateMany();
}
}
class RepeatInstantiateMany extends BenchmarkBase {
const RepeatInstantiateMany()
: super('$benchmarkName.RepeatInstantiateMany');
@override
void setup() {
// Run once to make sure the instantiations are cached, in case this
// benchmark is run on its own.
instantiateMany();
}
// Only call run once, so this is directly comparable to InstantiateMany.
@override
void exercise() => run();
@override
void run() {
instantiateMany();
}
}
@pragma('vm:never-inline')
void blackhole<T>() => null;
class B {}
class D<T> {
@pragma('vm:never-inline')
static void instantiate<T>() => blackhole<D<T>>();
}
''');
}
void generateInstantiateOnce(IOSink output) {
for (int i = 0; i < instantiateOnceCount; i++) {
output
..writeln('class A${i}<T> {}')
..writeln('');
}
output.writeln('void instantiateOnce<T>() {');
for (int i = 0; i < instantiateOnceCount; i++) {
output.writeln(' blackhole<A${i}<T>>();');
}
output
..writeln('}')
..writeln('');
}
void generateInstantiateMany(IOSink output) {
for (int i = 0; i < instantiateManyCount; i++) {
output
..writeln('class C${i} {}')
..writeln('');
}
output.writeln('void instantiateMany() {');
for (int i = 0; i < instantiateOnceCount; i++) {
output.writeln(' D.instantiate<C${i}>();');
}
output.writeln('}');
}
void main() {
final dartFilePath = path.join(
path.dirname(Platform.script.path), 'dart', '$benchmarkName.dart');
final dartSink = File(dartFilePath).openWrite();
generateBenchmarkClassesAndUtilities(dartSink, nnbd: true);
generateInstantiateOnce(dartSink);
generateInstantiateMany(dartSink);
dartSink..flush();
final dart2FilePath = path.join(
path.dirname(Platform.script.path), 'dart2', '$benchmarkName.dart');
final dart2Sink = File(dart2FilePath).openWrite();
generateBenchmarkClassesAndUtilities(dart2Sink, nnbd: false);
generateInstantiateOnce(dart2Sink);
generateInstantiateMany(dart2Sink);
dart2Sink..flush();
}