mirror of
https://github.com/dart-lang/sdk
synced 2024-10-03 00:29:50 +00:00
[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>
This commit is contained in:
parent
45e205b193
commit
b341480a72
197
benchmarks/TypeLiteral/dart/TypeLiteral.dart
Normal file
197
benchmarks/TypeLiteral/dart/TypeLiteral.dart
Normal file
|
@ -0,0 +1,197 @@
|
|||
// 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.');
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue