mirror of
https://github.com/dart-lang/sdk
synced 2024-10-04 20:29:39 +00:00
af1b5b8044
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>
534 lines
12 KiB
Dart
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());
|
|
}
|
|
}
|
|
}
|