blob: 545b300f208e430f5bfed64a0abbeed37da84123 [file] [log] [blame]
// 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 'package:benchmark_harness/benchmark_harness.dart';
// Micro-benchmark for taking tear-off of instance method multiple
// times and in a loop.
class BenchTearOffInlined extends BenchmarkBase {
BenchTearOffInlined() : super('TearOff.Inlined');
int sum = 0;
@pragma('vm:prefer-inline')
@pragma('wasm:prefer-inline')
@pragma('dart2js:prefer-inline')
void foo(int arg) {
sum += arg;
}
@pragma('vm:prefer-inline')
@pragma('wasm:prefer-inline')
@pragma('dart2js:prefer-inline')
void callIt(void Function(int) func, int arg) {
func(arg);
}
@override
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
@pragma('dart2js:never-inline')
void run() {
sum = 0;
callIt(foo, 1);
callIt(foo, 2);
callIt(foo, 3);
callIt(foo, 4);
callIt(foo, 5);
for (int i = 11; i < 20; ++i) {
callIt(foo, i);
}
callIt(foo, 6);
callIt(foo, 7);
callIt(foo, 8);
callIt(foo, 9);
callIt(foo, 10);
const int expectedSum = 20 * (20 - 1) ~/ 2;
if (sum != expectedSum) throw 'Bad result: $sum';
}
}
class BenchTearOffInlinedInTry extends BenchmarkBase {
BenchTearOffInlinedInTry() : super('TearOff.Inlined.InTry');
int sum = 0;
@pragma('vm:prefer-inline')
@pragma('wasm:prefer-inline')
@pragma('dart2js:prefer-inline')
void foo(int arg) {
sum += arg;
}
@pragma('vm:prefer-inline')
@pragma('wasm:prefer-inline')
@pragma('dart2js:prefer-inline')
void callIt(void Function(int) func, int arg) {
func(arg);
}
@override
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
@pragma('dart2js:never-inline')
void run() {
sum = 0;
try {
callIt(foo, 1);
callIt(foo, 2);
callIt(foo, 3);
callIt(foo, 4);
callIt(foo, 5);
for (int i = 11; i < 20; ++i) {
callIt(foo, i);
}
callIt(foo, 6);
callIt(foo, 7);
callIt(foo, 8);
callIt(foo, 9);
callIt(foo, 10);
} finally {
const int expectedSum = 20 * (20 - 1) ~/ 2;
if (sum != expectedSum) throw 'Bad result: $sum';
}
}
}
class BenchTearOffNotInlined extends BenchmarkBase {
BenchTearOffNotInlined() : super('TearOff.NotInlined');
int sum = 0;
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
@pragma('dart2js:never-inline')
void foo(int arg) {
sum += arg;
}
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
@pragma('dart2js:never-inline')
void callIt(void Function(int) func, int arg) {
func(arg);
}
@override
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
@pragma('dart2js:never-inline')
void run() {
sum = 0;
callIt(foo, 1);
callIt(foo, 2);
callIt(foo, 3);
callIt(foo, 4);
callIt(foo, 5);
for (int i = 11; i < 20; ++i) {
callIt(foo, i);
}
callIt(foo, 6);
callIt(foo, 7);
callIt(foo, 8);
callIt(foo, 9);
callIt(foo, 10);
const int expectedSum = 20 * (20 - 1) ~/ 2;
if (sum != expectedSum) throw 'Bad result: $sum';
}
}
class BenchTearOffNotInlinedInTry extends BenchmarkBase {
BenchTearOffNotInlinedInTry() : super('TearOff.NotInlined.InTry');
int sum = 0;
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
@pragma('dart2js:never-inline')
void foo(int arg) {
sum += arg;
}
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
@pragma('dart2js:never-inline')
void callIt(void Function(int) func, int arg) {
func(arg);
}
@override
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
@pragma('dart2js:never-inline')
void run() {
sum = 0;
try {
callIt(foo, 1);
callIt(foo, 2);
callIt(foo, 3);
callIt(foo, 4);
callIt(foo, 5);
for (int i = 11; i < 20; ++i) {
callIt(foo, i);
}
callIt(foo, 6);
callIt(foo, 7);
callIt(foo, 8);
callIt(foo, 9);
callIt(foo, 10);
} finally {
const int expectedSum = 20 * (20 - 1) ~/ 2;
if (sum != expectedSum) throw 'Bad result: $sum';
}
}
}
void main() {
final benchmarks = [
BenchTearOffInlined(),
BenchTearOffInlinedInTry(),
BenchTearOffNotInlined(),
BenchTearOffNotInlinedInTry(),
];
for (final benchmark in benchmarks) {
benchmark.warmup();
}
for (final benchmark in benchmarks) {
benchmark.report();
}
}