| {{/* |
| // Copyright 2022 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| */}} |
| |
| // Copyright 2020 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // @dart = 2.8 |
| |
| import 'dart:convert'; |
| import 'dart:io' hide exit; |
| import 'dart:typed_data'; |
| |
| import 'package:fidl/fidl.dart'; |
| import 'package:fidl_test_benchmarkfidl/fidl_async.dart'; |
| import 'package:fuchsia/fuchsia.dart'; |
| import 'package:sl4f/sl4f.dart'; |
| import 'package:test/test.dart'; |
| {{- if .UsesHandles }} |
| import 'package:sdk.dart.lib.gidl/handles.dart'; |
| {{- end }} |
| |
| typedef _CallbackSetter = void Function(void Function()); |
| typedef _DefinitionBlock = void Function( |
| _CallbackSetter run, _CallbackSetter teardown); |
| |
| class _Definition { |
| final String name; |
| final _DefinitionBlock block; |
| |
| void Function() _run; |
| void Function() _teardown; |
| |
| _Definition(this.name, this.block); |
| |
| double execute() { |
| block((void Function() run) => _run = run, |
| (void Function() teardown) => _teardown = teardown); |
| if (_run == null) { |
| throw Exception("Benchmark $name doesn't declare what to run."); |
| } |
| |
| // Warmup for at least 100ms. Discard result. |
| _measure(100); |
| |
| // Run the benchmark for at least 1s. |
| double result = _measure(1000); |
| |
| if (_teardown != null) { |
| _teardown(); |
| } |
| |
| print('$name $result ms\n'); |
| return result; |
| } |
| |
| // Measures the score for this benchmark by executing it repeateldy until |
| // time minimum has been reached. |
| double _measure(int minimumMillis) { |
| int minimumMicros = minimumMillis * 1000; |
| int iter = 0; |
| Stopwatch watch = Stopwatch()..start(); |
| int elapsed = 0; |
| while (elapsed < minimumMicros) { |
| _run(); |
| elapsed = watch.elapsedMicroseconds; |
| iter++; |
| } |
| return elapsed / iter; |
| } |
| } |
| |
| class BenchmarkGroup { |
| final List<_Definition> definitions; |
| final String name; |
| |
| BenchmarkGroup(this.name) : definitions = []; |
| |
| void benchmark(final String name, final _DefinitionBlock block) { |
| definitions.add(_Definition(name, block)); |
| } |
| |
| List<TestCaseResults> run() { |
| final List<TestCaseResults> results = []; |
| for (final def in definitions) { |
| final result = def.execute(); |
| results.add(TestCaseResults(def.name, Unit.nanoseconds, [result * 1000])); |
| } |
| return results; |
| } |
| } |
| |
| {{ range .Benchmarks }} |
| void encode{{ .Name }}Benchmark(run, teardown) { |
| {{- if .HandleDefs }} |
| final handles = createHandles({{ .HandleDefs }}); |
| teardown(() { |
| closeHandles(handles); |
| }); |
| {{- end }} |
| final value = {{ .Value }}; |
| run(() { |
| final Encoder encoder = Encoder(kWireFormatDefault) |
| ..alloc({{ .ValueType}}.inlineSize, 0); |
| {{ .ValueType }}.encode(encoder, value, 0, 1); |
| }); |
| } |
| void decode{{ .Name }}Benchmark(run, teardown) { |
| {{- if .HandleDefs }} |
| final handles = createHandles({{ .HandleDefs }}); |
| teardown(() { |
| closeHandles(handles); |
| }); |
| {{- end }} |
| final value = {{ .Value }}; |
| final Encoder encoder = Encoder(kWireFormatDefault) |
| ..alloc(kMessageHeaderSize + {{ .ValueType}}.inlineSize, 0); |
| {{ .ValueType }}.encode(encoder, value, kMessageHeaderSize, 1); |
| run(() { |
| final Decoder decoder = Decoder(IncomingMessage.fromOutgoingMessage(encoder.message)) |
| ..claimBytes(kMessageHeaderSize + {{ .ValueType}}.inlineSize, 0); |
| {{ .ValueType }}.decode(decoder, kMessageHeaderSize, 1); |
| }); |
| } |
| {{ end }} |
| |
| List<Map<String, dynamic>> resultsToJson( |
| List<TestCaseResults> results, String suiteName) { |
| return results.map((result) => result.toJson(testSuite: suiteName)).toList(); |
| } |
| |
| void main() async { |
| test('main', () async { |
| final benchmarks = BenchmarkGroup('fuchsia.fidl_microbenchmarks') |
| {{ range .Benchmarks }} |
| ..benchmark('Dart/Encode/{{ .ChromeperfPath }}/WallTime', encode{{.Name}}Benchmark) |
| ..benchmark('Dart/Decode/{{ .ChromeperfPath }}/WallTime', decode{{.Name}}Benchmark) |
| {{ end }}; |
| |
| final results = benchmarks.run(); |
| if (results.isEmpty) { |
| exit(1); |
| } |
| |
| var encoder = JsonEncoder.withIndent(' '); |
| await File('/data/results.json').writeAsString( |
| encoder.convert(resultsToJson(results, benchmarks.name)), |
| mode: FileMode.write); |
| }, timeout: Timeout(Duration(minutes: 10))); |
| } |