dart-sdk/benchmarks/Dynamic/dart/Dynamic.dart
Martin Kustermann af1b5b8044 [dart2wasm] Switch binaryen optimization levels from -O3 to -Os
We want dart2wasm be comparable to dart2js / dart2aot, the ladder two
are much more conservative with inlining compared to current dart2wasm.

The -O3 is described in the binaryen sources as agressive for
performance and therefore willing to compromise code size.

The -Os is more nuanced: It will perform many optimizations that are
done in -O3 (and e.g. not in -O2) but it will make inlining less
agressive.

This reduces flute compile-time by 10% and code size by 10%
This benchmark results are mixed (some things get faster, some things
slower). Naturally there'll be specialized micro benchmarks that
get hit hard by this.

Where performance matters we should rather make dart2wasm use better
inlining heuristics and annotate code with
`@pragma('wasm:prefer-inline')`

Change-Id: Idf7e75e4e385629c9cec66359efe0afe50db3e72
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/352523
Reviewed-by: Slava Egorov <vegorov@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
2024-02-14 13:45:13 +00:00

534 lines
12 KiB
Dart

// Copyright (c) 2020, 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 dynamically calling functions
// and closures by calling a set of functions and closures, testing non-dynamic
// calls, calls after casting the function tearoff or closure to dynamic, and
// similarly defined functions and closures except that the parameters and
// return types are all dynamic.
import 'package:benchmark_harness/benchmark_harness.dart';
const int kRepeat = 100;
void main() {
const NonDynamicFunction().report();
const NonDynamicFunctionOptSkipped().report();
const NonDynamicFunctionOptProvided().report();
const NonDynamicFunctionNamedSkipped().report();
const NonDynamicFunctionNamedProvided().report();
const NonDynamicClosure().report();
const NonDynamicClosureOptSkipped().report();
const NonDynamicClosureOptProvided().report();
const NonDynamicClosureNamedSkipped().report();
const NonDynamicClosureNamedProvided().report();
const DynamicCastFunction().report();
const DynamicCastFunctionOptSkipped().report();
const DynamicCastFunctionOptProvided().report();
const DynamicCastFunctionNamedSkipped().report();
const DynamicCastFunctionNamedProvided().report();
const DynamicCastClosure().report();
const DynamicCastClosureOptSkipped().report();
const DynamicCastClosureOptProvided().report();
const DynamicCastClosureNamedSkipped().report();
const DynamicCastClosureNamedProvided().report();
const DynamicDefFunction().report();
const DynamicDefFunctionOptSkipped().report();
const DynamicDefFunctionOptProvided().report();
const DynamicDefFunctionNamedSkipped().report();
const DynamicDefFunctionNamedProvided().report();
const DynamicDefClosure().report();
const DynamicDefClosureOptSkipped().report();
const DynamicDefClosureOptProvided().report();
const DynamicDefClosureNamedSkipped().report();
const DynamicDefClosureNamedProvided().report();
const DynamicClassASingleton().report();
const DynamicClassBSingleton().report();
const DynamicClassCFresh().report();
const DynamicClassDFresh().report();
}
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
void f1(String s) {}
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
Function(String) c1 = (String s) => {};
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
void f2(String s, [String t = 'default']) {}
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
Function(String, [String]) c2 = (String s, [String t = 'default']) => {};
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
void f3(String s, {String t = 'default'}) {}
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
Function(String, {String t}) c3 = (String s, {String t = 'default'}) => {};
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
dynamic df1 = f1 as dynamic;
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
dynamic dc1 = c1 as dynamic;
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
dynamic df2 = f2 as dynamic;
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
dynamic dc2 = c2 as dynamic;
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
dynamic df3 = f3 as dynamic;
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
dynamic dc3 = c3 as dynamic;
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
dynamic df1NonCast(dynamic s) {}
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
Function dc1NonCast = (dynamic s) => {};
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
dynamic df2NonCast(dynamic s, [dynamic t = 'default']) {}
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
Function dc2NonCast = (dynamic s, [dynamic t = 'default']) => {};
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
dynamic df3NonCast(dynamic s, {dynamic t = 'default'}) {}
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
Function dc3NonCast = (dynamic s, {dynamic t = 'default'}) => {};
class A {
const A();
}
class B extends A {
const B();
}
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
dynamic k = (A a) {};
class C {
C();
}
class D extends C {
D();
}
@pragma('vm:never-inline')
@pragma('wasm:never-inline')
dynamic j = (C c) {};
class NonDynamicFunction extends BenchmarkBase {
const NonDynamicFunction() : super('Dynamic.NonDynamicFunction');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
f1('');
}
}
}
class NonDynamicClosure extends BenchmarkBase {
const NonDynamicClosure() : super('Dynamic.NonDynamicClosure');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
c1('');
}
}
}
class NonDynamicFunctionOptSkipped extends BenchmarkBase {
const NonDynamicFunctionOptSkipped()
: super('Dynamic.NonDynamicFunctionOptSkipped');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
f2('');
}
}
}
class NonDynamicFunctionOptProvided extends BenchmarkBase {
const NonDynamicFunctionOptProvided()
: super('Dynamic.NonDynamicFunctionOptProvided');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
f2('', '');
}
}
}
class NonDynamicFunctionNamedSkipped extends BenchmarkBase {
const NonDynamicFunctionNamedSkipped()
: super('Dynamic.NonDynamicFunctionNamedSkipped');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
f3('');
}
}
}
class NonDynamicFunctionNamedProvided extends BenchmarkBase {
const NonDynamicFunctionNamedProvided()
: super('Dynamic.NonDynamicFunctionNamedProvided');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
f3('', t: '');
}
}
}
class NonDynamicClosureOptSkipped extends BenchmarkBase {
const NonDynamicClosureOptSkipped()
: super('Dynamic.NonDynamicClosureOptSkipped');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
c2('');
}
}
}
class NonDynamicClosureOptProvided extends BenchmarkBase {
const NonDynamicClosureOptProvided()
: super('Dynamic.NonDynamicClosureOptProvided');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
c2('', '');
}
}
}
class NonDynamicClosureNamedSkipped extends BenchmarkBase {
const NonDynamicClosureNamedSkipped()
: super('Dynamic.NonDynamicClosureNamedSkipped');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
c3('');
}
}
}
class NonDynamicClosureNamedProvided extends BenchmarkBase {
const NonDynamicClosureNamedProvided()
: super('Dynamic.NonDynamicClosureNamedProvided');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
c3('', t: '');
}
}
}
class DynamicCastFunction extends BenchmarkBase {
const DynamicCastFunction() : super('Dynamic.DynamicCastFunction');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
df1('');
}
}
}
class DynamicCastClosure extends BenchmarkBase {
const DynamicCastClosure() : super('Dynamic.DynamicCastClosure');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
dc1('');
}
}
}
class DynamicCastFunctionOptSkipped extends BenchmarkBase {
const DynamicCastFunctionOptSkipped()
: super('Dynamic.DynamicCastFunctionOptSkipped');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
df2('');
}
}
}
class DynamicCastFunctionOptProvided extends BenchmarkBase {
const DynamicCastFunctionOptProvided()
: super('Dynamic.DynamicCastFunctionOptProvided');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
df2('', '');
}
}
}
class DynamicCastFunctionNamedSkipped extends BenchmarkBase {
const DynamicCastFunctionNamedSkipped()
: super('Dynamic.DynamicCastFunctionNamedSkipped');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
df3('');
}
}
}
class DynamicCastFunctionNamedProvided extends BenchmarkBase {
const DynamicCastFunctionNamedProvided()
: super('Dynamic.DynamicCastFunctionNamedProvided');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
df3('', t: '');
}
}
}
class DynamicCastClosureOptSkipped extends BenchmarkBase {
const DynamicCastClosureOptSkipped()
: super('Dynamic.DynamicCastClosureOptSkipped');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
dc2('');
}
}
}
class DynamicCastClosureOptProvided extends BenchmarkBase {
const DynamicCastClosureOptProvided()
: super('Dynamic.DynamicCastClosureOptProvided');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
dc2('', '');
}
}
}
class DynamicCastClosureNamedSkipped extends BenchmarkBase {
const DynamicCastClosureNamedSkipped()
: super('Dynamic.DynamicCastClosureNamedSkipped');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
dc3('');
}
}
}
class DynamicCastClosureNamedProvided extends BenchmarkBase {
const DynamicCastClosureNamedProvided()
: super('Dynamic.DynamicCastClosureNamedProvided');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
dc3('', t: '');
}
}
}
class DynamicDefFunction extends BenchmarkBase {
const DynamicDefFunction() : super('Dynamic.DynamicDefFunction');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
df1NonCast('');
}
}
}
class DynamicDefClosure extends BenchmarkBase {
const DynamicDefClosure() : super('Dynamic.DynamicDefClosure');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
dc1NonCast('');
}
}
}
class DynamicDefFunctionOptSkipped extends BenchmarkBase {
const DynamicDefFunctionOptSkipped()
: super('Dynamic.DynamicDefFunctionOptSkipped');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
df2NonCast('');
}
}
}
class DynamicDefFunctionOptProvided extends BenchmarkBase {
const DynamicDefFunctionOptProvided()
: super('Dynamic.DynamicDefFunctionOptProvided');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
df2NonCast('', '');
}
}
}
class DynamicDefFunctionNamedSkipped extends BenchmarkBase {
const DynamicDefFunctionNamedSkipped()
: super('Dynamic.DynamicDefFunctionNamedSkipped');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
df3NonCast('');
}
}
}
class DynamicDefFunctionNamedProvided extends BenchmarkBase {
const DynamicDefFunctionNamedProvided()
: super('Dynamic.DynamicDefFunctionNamedProvided');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
df3NonCast('', t: '');
}
}
}
class DynamicDefClosureOptSkipped extends BenchmarkBase {
const DynamicDefClosureOptSkipped()
: super('Dynamic.DynamicDefClosureOptSkipped');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
dc2NonCast('');
}
}
}
class DynamicDefClosureOptProvided extends BenchmarkBase {
const DynamicDefClosureOptProvided()
: super('Dynamic.DynamicDefClosureOptProvided');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
dc2NonCast('', '');
}
}
}
class DynamicDefClosureNamedSkipped extends BenchmarkBase {
const DynamicDefClosureNamedSkipped()
: super('Dynamic.DynamicDefClosureNamedSkipped');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
dc3NonCast('');
}
}
}
class DynamicDefClosureNamedProvided extends BenchmarkBase {
const DynamicDefClosureNamedProvided()
: super('Dynamic.DynamicDefClosureNamedProvided');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
dc3NonCast('', t: '');
}
}
}
class DynamicClassASingleton extends BenchmarkBase {
final A a;
const DynamicClassASingleton()
: a = const A(),
super('Dynamic.DynamicClassASingleton');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
k(a);
}
}
}
class DynamicClassBSingleton extends BenchmarkBase {
final B b;
const DynamicClassBSingleton()
: b = const B(),
super('Dynamic.DynamicClassBSingleton');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
k(b);
}
}
}
class DynamicClassCFresh extends BenchmarkBase {
const DynamicClassCFresh() : super('Dynamic.DynamicClassCFresh');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
j(C());
}
}
}
class DynamicClassDFresh extends BenchmarkBase {
const DynamicClassDFresh() : super('Dynamic.DynamicClassDFresh');
@override
void run() {
for (int i = 0; i < kRepeat; i++) {
j(D());
}
}
}