dart-sdk/benchmarks/TypeLiteral/dart/TypeLiteral.dart
Martin Kustermann b341480a72 [vm] Add TypeLiteral benchmark
This benchmark tests the performance of uninstantiated type literal
usages.

Issue https://github.com/dart-lang/sdk/issues/48757

TEST=ci

Change-Id: I5eb881a2b8e397997505af41b24240afcbe9d1ac
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/242104
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
2022-04-25 08:49:12 +00:00

198 lines
5.5 KiB
Dart

// 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.
const int iterations = 100000;
void main() {
SyncCallBenchmark('TypeLiteral.GenericFunction.T.dynamic', () {
for (int i = 0; i < iterations; ++i) {
getT<dynamic>();
}
return iterations;
}).report();
SyncCallBenchmark('TypeLiteral.GenericFunction.T.int', () {
for (int i = 0; i < iterations; ++i) {
getT<int>();
}
return iterations;
}).report();
SyncCallBenchmark('TypeLiteral.GenericFunction.T.nullableInt', () {
for (int i = 0; i < iterations; ++i) {
getT<int?>();
}
return iterations;
}).report();
SyncCallBenchmark('TypeLiteral.GenericFunction.ListOfT.int', () {
for (int i = 0; i < iterations; ++i) {
getListOfT<int>();
}
return iterations;
}).report();
SyncCallBenchmark('TypeLiteral.GenericFunction.ListOfT.nullableInt', () {
for (int i = 0; i < iterations; ++i) {
getListOfT<int?>();
}
return iterations;
}).report();
SyncCallBenchmark('TypeLiteral.GenericFunction.NullableT.int', () {
for (int i = 0; i < iterations; ++i) {
getNullableT<int>();
}
return iterations;
}).report();
SyncCallBenchmark('TypeLiteral.GenericFunction.NullableT.nullableInt', () {
for (int i = 0; i < iterations; ++i) {
getNullableT<int?>();
}
return iterations;
}).report();
SyncCallBenchmark('TypeLiteral.GenericFunction.ListOfNullableT.int', () {
for (int i = 0; i < iterations; ++i) {
getListOfT<int>();
}
return iterations;
}).report();
SyncCallBenchmark('TypeLiteral.GenericFunction.ListOfNullableT.nullableInt',
() {
for (int i = 0; i < iterations; ++i) {
getListOfNullableT<int?>();
}
return iterations;
}).report();
final foos = <Foo<Object?>>[
Foo<int>(),
Foo<int?>(),
Foo<dynamic>(),
];
final Foo fooInt = foos[int.parse('0')];
final Foo fooNullableInt = foos[int.parse('1')];
final Foo fooDynamic = foos[int.parse('2')];
SyncCallBenchmark('TypeLiteral.GenericClass.T.dynamic', () {
for (int i = 0; i < iterations; ++i) {
fooDynamic.getT();
}
return iterations;
}).report();
SyncCallBenchmark('TypeLiteral.GenericClass.T.int', () {
for (int i = 0; i < iterations; ++i) {
fooInt.getT();
}
return iterations;
}).report();
SyncCallBenchmark('TypeLiteral.GenericClass.T.nullableInt', () {
for (int i = 0; i < iterations; ++i) {
fooNullableInt.getT();
}
return iterations;
}).report();
SyncCallBenchmark('TypeLiteral.GenericClass.ListOfT.int', () {
for (int i = 0; i < iterations; ++i) {
fooInt.getListOfT();
}
return iterations;
}).report();
SyncCallBenchmark('TypeLiteral.GenericClass.ListOfT.nullableInt', () {
for (int i = 0; i < iterations; ++i) {
fooNullableInt.getListOfT();
}
return iterations;
}).report();
SyncCallBenchmark('TypeLiteral.GenericClass.NullableT.int', () {
for (int i = 0; i < iterations; ++i) {
fooInt.getNullableT();
}
return iterations;
}).report();
SyncCallBenchmark('TypeLiteral.GenericClass.NullableT.nullableInt', () {
for (int i = 0; i < iterations; ++i) {
fooNullableInt.getNullableT();
}
return iterations;
}).report();
SyncCallBenchmark('TypeLiteral.GenericClass.ListOfNullableT.int', () {
for (int i = 0; i < iterations; ++i) {
fooInt.getListOfT();
}
return iterations;
}).report();
SyncCallBenchmark('TypeLiteral.GenericClass.ListOfNullableT.nullableInt', () {
for (int i = 0; i < iterations; ++i) {
fooNullableInt.getListOfNullableT();
}
return iterations;
}).report();
}
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Type getT<T>() => T;
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Type getNullableT<T>() => MakeNullable<T?>;
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Type getListOfT<T>() => List<T>;
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Type getListOfNullableT<T>() => List<T?>;
class Foo<T> {
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Type getT() => T;
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Type getNullableT() => MakeNullable<T?>;
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Type getListOfT() => List<T>;
@pragma('vm:never-inline')
@pragma('dart2js:noInline')
Type getListOfNullableT() => List<T?>;
}
typedef MakeNullable<X> = X?;
// Same as from [Calls] benchmark.
class SyncCallBenchmark {
final String name;
final int Function() performCalls;
SyncCallBenchmark(this.name, this.performCalls);
// Returns the number of nanoseconds per call.
double measureFor(Duration duration) {
final sw = Stopwatch()..start();
final durationInMicroseconds = duration.inMicroseconds;
int numberOfCalls = 0;
int totalMicroseconds = 0;
do {
numberOfCalls += performCalls();
totalMicroseconds = sw.elapsedMicroseconds;
} while (totalMicroseconds < durationInMicroseconds);
final int totalNanoseconds = sw.elapsed.inMicroseconds * 1000;
return totalNanoseconds / numberOfCalls;
}
// Runs warmup phase, runs benchmark and reports result.
void report() {
// Warmup for 100 ms.
measureFor(const Duration(milliseconds: 100));
// Run benchmark for 2 seconds.
final double nsPerCall = measureFor(const Duration(seconds: 2));
// Report result.
print('$name(RunTimeRaw): $nsPerCall ns.');
}
}