-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge 9896f1c into dev
- Loading branch information
Showing
60 changed files
with
2,346 additions
and
661 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.