From e7eb0aaa20c7117085f0f875ca6e9467d7e10b0c Mon Sep 17 00:00:00 2001 From: Alexander Markov Date: Wed, 7 Feb 2024 15:16:19 +0000 Subject: [PATCH] [benchmarks] Add benchmark for taking tear-offs repeatedly Issue: https://github.com/dart-lang/sdk/issues/54808 Change-Id: Ice28033bab71e30f9a586564d7e55d9c4f5ce770 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/350640 Reviewed-by: Martin Kustermann Commit-Queue: Alexander Markov --- benchmarks/TearOff/dart/TearOff.dart | 192 +++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 benchmarks/TearOff/dart/TearOff.dart diff --git a/benchmarks/TearOff/dart/TearOff.dart b/benchmarks/TearOff/dart/TearOff.dart new file mode 100644 index 000000000000..6fa9bb103b40 --- /dev/null +++ b/benchmarks/TearOff/dart/TearOff.dart @@ -0,0 +1,192 @@ +// 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('dart2js:prefer-inline') + void foo(int arg) { + sum += arg; + } + + @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') + void callIt(void Function(int) func, int arg) { + func(arg); + } + + @override + @pragma('vm: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('dart2js:prefer-inline') + void foo(int arg) { + sum += arg; + } + + @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') + void callIt(void Function(int) func, int arg) { + func(arg); + } + + @override + @pragma('vm: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('dart2js:never-inline') + void foo(int arg) { + sum += arg; + } + + @pragma('vm:never-inline') + @pragma('dart2js:never-inline') + void callIt(void Function(int) func, int arg) { + func(arg); + } + + @override + @pragma('vm: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('dart2js:never-inline') + void foo(int arg) { + sum += arg; + } + + @pragma('vm:never-inline') + @pragma('dart2js:never-inline') + void callIt(void Function(int) func, int arg) { + func(arg); + } + + @override + @pragma('vm: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(); + } +}