mirror of
https://github.com/dart-lang/sdk
synced 2024-10-03 00:45:16 +00:00
[benchmarks] Micro-benchmark for multiple returns
The new micro-benchmark measures performance of returning 2 values via list, dedicated class, record and a record with named fields. Requires '--enable-experiment=records' flag to run. Issue: https://github.com/dart-lang/sdk/issues/49719 Change-Id: I895d955efb2fc4f1c04b31b113cd8e01db47132a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/265121 Reviewed-by: Slava Egorov <vegorov@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
parent
5caa8da9c4
commit
6897b9e331
287
benchmarks/MultipleReturns/dart/MultipleReturns.dart
Normal file
287
benchmarks/MultipleReturns/dart/MultipleReturns.dart
Normal file
|
@ -0,0 +1,287 @@
|
|||
// 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.
|
||||
|
||||
import 'package:benchmark_harness/benchmark_harness.dart';
|
||||
|
||||
// Micro-benchmark for multiple returns.
|
||||
//
|
||||
// The goal of this benchmark is to compare and track performance of
|
||||
// various ways to return multiple values from a method.
|
||||
|
||||
int input1 = int.parse('42');
|
||||
String input2 = input1.toString();
|
||||
|
||||
const int N = 1000000;
|
||||
final int expectedSum = (input1 + input2.length) * N;
|
||||
|
||||
class ResultClass {
|
||||
final int result0;
|
||||
final String result1;
|
||||
const ResultClass(this.result0, this.result1);
|
||||
}
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@pragma('dart2js:prefer-inline')
|
||||
List<Object> inlinedList() => [input1, input2];
|
||||
|
||||
@pragma('vm:never-inline')
|
||||
@pragma('dart2js:never-inline')
|
||||
List<Object> notInlinedList() => [input1, input2];
|
||||
|
||||
@pragma('vm:never-inline')
|
||||
@pragma('dart2js:never-inline')
|
||||
List<Object> forwardedList() => notInlinedList();
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@pragma('dart2js:prefer-inline')
|
||||
ResultClass inlinedClass() => ResultClass(input1, input2);
|
||||
|
||||
@pragma('vm:never-inline')
|
||||
@pragma('dart2js:never-inline')
|
||||
ResultClass notInlinedClass() => ResultClass(input1, input2);
|
||||
|
||||
@pragma('vm:never-inline')
|
||||
@pragma('dart2js:never-inline')
|
||||
ResultClass forwardedClass() => notInlinedClass();
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@pragma('dart2js:prefer-inline')
|
||||
(int, String) inlinedRecord() => (input1, input2);
|
||||
|
||||
@pragma('vm:never-inline')
|
||||
@pragma('dart2js:never-inline')
|
||||
(int, String) notInlinedRecord() => (input1, input2);
|
||||
|
||||
@pragma('vm:never-inline')
|
||||
@pragma('dart2js:never-inline')
|
||||
(int, String) forwardedRecord() => notInlinedRecord();
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@pragma('dart2js:prefer-inline')
|
||||
({int result0, String result1}) inlinedRecordNamed() => (result0: input1, result1: input2);
|
||||
|
||||
@pragma('vm:never-inline')
|
||||
@pragma('dart2js:never-inline')
|
||||
({int result0, String result1}) notInlinedRecordNamed() => (result0: input1, result1: input2);
|
||||
|
||||
@pragma('vm:never-inline')
|
||||
@pragma('dart2js:never-inline')
|
||||
({int result0, String result1}) forwardedRecordNamed() => notInlinedRecordNamed();
|
||||
|
||||
class BenchInlinedList extends BenchmarkBase {
|
||||
BenchInlinedList() : super('MultipleReturns.Inlined.List');
|
||||
|
||||
@override
|
||||
void run() {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < N; ++i) {
|
||||
final result = inlinedList();
|
||||
final int r0 = result[0] as int;
|
||||
final String r1 = result[1] as String;
|
||||
sum += r0 + r1.length;
|
||||
}
|
||||
if (sum != expectedSum) throw 'Bad result: $sum';
|
||||
}
|
||||
}
|
||||
|
||||
class BenchNotInlinedList extends BenchmarkBase {
|
||||
BenchNotInlinedList() : super('MultipleReturns.NotInlined.List');
|
||||
|
||||
@override
|
||||
void run() {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < N; ++i) {
|
||||
final result = notInlinedList();
|
||||
final int r0 = result[0] as int;
|
||||
final String r1 = result[1] as String;
|
||||
sum += r0 + r1.length;
|
||||
}
|
||||
if (sum != expectedSum) throw 'Bad result: $sum';
|
||||
}
|
||||
}
|
||||
|
||||
class BenchForwardedList extends BenchmarkBase {
|
||||
BenchForwardedList() : super('MultipleReturns.Forwarded.List');
|
||||
|
||||
@override
|
||||
void run() {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < N; ++i) {
|
||||
final result = forwardedList();
|
||||
final int r0 = result[0] as int;
|
||||
final String r1 = result[1] as String;
|
||||
sum += r0 + r1.length;
|
||||
}
|
||||
if (sum != expectedSum) throw 'Bad result: $sum';
|
||||
}
|
||||
}
|
||||
|
||||
class BenchInlinedClass extends BenchmarkBase {
|
||||
BenchInlinedClass() : super('MultipleReturns.Inlined.Class');
|
||||
|
||||
@override
|
||||
void run() {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < N; ++i) {
|
||||
final result = inlinedClass();
|
||||
final int r0 = result.result0;
|
||||
final String r1 = result.result1;
|
||||
sum += r0 + r1.length;
|
||||
}
|
||||
if (sum != expectedSum) throw 'Bad result: $sum';
|
||||
}
|
||||
}
|
||||
|
||||
class BenchNotInlinedClass extends BenchmarkBase {
|
||||
BenchNotInlinedClass() : super('MultipleReturns.NotInlined.Class');
|
||||
|
||||
@override
|
||||
void run() {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < N; ++i) {
|
||||
final result = notInlinedClass();
|
||||
final int r0 = result.result0;
|
||||
final String r1 = result.result1;
|
||||
sum += r0 + r1.length;
|
||||
}
|
||||
if (sum != expectedSum) throw 'Bad result: $sum';
|
||||
}
|
||||
}
|
||||
|
||||
class BenchForwardedClass extends BenchmarkBase {
|
||||
BenchForwardedClass() : super('MultipleReturns.Forwarded.Class');
|
||||
|
||||
@override
|
||||
void run() {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < N; ++i) {
|
||||
final result = forwardedClass();
|
||||
final int r0 = result.result0;
|
||||
final String r1 = result.result1;
|
||||
sum += r0 + r1.length;
|
||||
}
|
||||
if (sum != expectedSum) throw 'Bad result: $sum';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class BenchInlinedRecord extends BenchmarkBase {
|
||||
BenchInlinedRecord() : super('MultipleReturns.Inlined.Record');
|
||||
|
||||
@override
|
||||
void run() {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < N; ++i) {
|
||||
final result = inlinedRecord();
|
||||
final int r0 = result.$0;
|
||||
final String r1 = result.$1;
|
||||
sum += r0 + r1.length;
|
||||
}
|
||||
if (sum != expectedSum) throw 'Bad result: $sum';
|
||||
}
|
||||
}
|
||||
|
||||
class BenchNotInlinedRecord extends BenchmarkBase {
|
||||
BenchNotInlinedRecord() : super('MultipleReturns.NotInlined.Record');
|
||||
|
||||
@override
|
||||
void run() {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < N; ++i) {
|
||||
final result = notInlinedRecord();
|
||||
final int r0 = result.$0;
|
||||
final String r1 = result.$1;
|
||||
sum += r0 + r1.length;
|
||||
}
|
||||
if (sum != expectedSum) throw 'Bad result: $sum';
|
||||
}
|
||||
}
|
||||
|
||||
class BenchForwardedRecord extends BenchmarkBase {
|
||||
BenchForwardedRecord() : super('MultipleReturns.Forwarded.Record');
|
||||
|
||||
@override
|
||||
void run() {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < N; ++i) {
|
||||
final result = forwardedRecord();
|
||||
final int r0 = result.$0;
|
||||
final String r1 = result.$1;
|
||||
sum += r0 + r1.length;
|
||||
}
|
||||
if (sum != expectedSum) throw 'Bad result: $sum';
|
||||
}
|
||||
}
|
||||
|
||||
class BenchInlinedRecordNamed extends BenchmarkBase {
|
||||
BenchInlinedRecordNamed() : super('MultipleReturns.Inlined.RecordNamed');
|
||||
|
||||
@override
|
||||
void run() {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < N; ++i) {
|
||||
final result = inlinedRecordNamed();
|
||||
final int r0 = result.result0;
|
||||
final String r1 = result.result1;
|
||||
sum += r0 + r1.length;
|
||||
}
|
||||
if (sum != expectedSum) throw 'Bad result: $sum';
|
||||
}
|
||||
}
|
||||
|
||||
class BenchNotInlinedRecordNamed extends BenchmarkBase {
|
||||
BenchNotInlinedRecordNamed() : super('MultipleReturns.NotInlined.RecordNamed');
|
||||
|
||||
@override
|
||||
void run() {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < N; ++i) {
|
||||
final result = notInlinedRecordNamed();
|
||||
final int r0 = result.result0;
|
||||
final String r1 = result.result1;
|
||||
sum += r0 + r1.length;
|
||||
}
|
||||
if (sum != expectedSum) throw 'Bad result: $sum';
|
||||
}
|
||||
}
|
||||
|
||||
class BenchForwardedRecordNamed extends BenchmarkBase {
|
||||
BenchForwardedRecordNamed() : super('MultipleReturns.Forwarded.RecordNamed');
|
||||
|
||||
@override
|
||||
void run() {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < N; ++i) {
|
||||
final result = forwardedRecordNamed();
|
||||
final int r0 = result.result0;
|
||||
final String r1 = result.result1;
|
||||
sum += r0 + r1.length;
|
||||
}
|
||||
if (sum != expectedSum) throw 'Bad result: $sum';
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
final benchmarks = [
|
||||
BenchInlinedList(),
|
||||
BenchInlinedClass(),
|
||||
BenchInlinedRecord(),
|
||||
BenchInlinedRecordNamed(),
|
||||
BenchNotInlinedList(),
|
||||
BenchNotInlinedClass(),
|
||||
BenchNotInlinedRecord(),
|
||||
BenchNotInlinedRecordNamed(),
|
||||
BenchForwardedList(),
|
||||
BenchForwardedClass(),
|
||||
BenchForwardedRecord(),
|
||||
BenchForwardedRecordNamed(),
|
||||
];
|
||||
|
||||
for (final benchmark in benchmarks) {
|
||||
benchmark.warmup();
|
||||
}
|
||||
for (final benchmark in benchmarks) {
|
||||
benchmark.report();
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue