blob: 05e6918b337284f7817603b9e750e0a6401e8716 [file] [log] [blame]
// Copyright (c) 2018, 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.
// ignore_for_file: uri_has_not_been_generated,undefined_identifier
/// Common platform independent benchmark infrastructure that can run
/// both on the VM and when compiled to JavaScript.
library common;
import 'dart:typed_data';
import 'package:benchmark_harness/benchmark_harness.dart';
import 'package:protobuf/protobuf.dart';
import 'temp/benchmarks.pb.dart';
import 'temp/datasets/google_message1/proto2/benchmark_message1_proto2.pb.dart'
as p2;
import 'temp/datasets/google_message1/proto3/benchmark_message1_proto3.pb.dart'
as p3;
import 'temp/datasets/google_message2/benchmark_message2.pb.dart';
import 'temp/datasets/google_message3/benchmark_message3.pb.dart';
import 'temp/datasets/google_message4/benchmark_message4.pb.dart';
/// Represents a dataset, a list of protobufs payloads, used for benchmarking.
/// All payloads are instances of the same message.
/// Datasets are loaded from BenchmarkDataset proto (see benchmark.proto).
class Dataset {
final String name;
/// Functions that can deserialize all payloads in this dataset.
final Factories factories;
/// List of packed payloads, which can be deserialized using [factories].
/// Used for binary deserialization benchmarks.
final List<Uint8List> packed = <Uint8List>[];
/// Messages deserialized from [packed] and then serialized back into JSON.
/// Used for JSON serialization benchmarks.
final List<String> asJson = <String>[];
/// Messages deserialized from [packed]. Used in serialization benchmarks.
final List<GeneratedMessage> unpacked = <GeneratedMessage>[];
/// Create [Dataset] from a [BenchmarkDataset] proto.
factory Dataset.fromBinary(List<int> binary) {
final dataSet = BenchmarkDataset.fromBuffer(binary);
final factories = Factories.forMessage(dataSet.messageName);
final ds = Dataset._(dataSet.name, factories);
for (var payload in dataSet.payload) {
final bytes = Uint8List.fromList(payload);
final msg = factories.fromBuffer(bytes);
ds.packed.add(bytes);
ds.unpacked.add(msg);
ds.asJson.add(msg.writeToJson());
}
return ds;
}
Dataset._(this.name, this.factories);
}
typedef FromBufferFactory = dynamic Function(List<int> binary);
typedef FromJsonFactory = dynamic Function(String json);
class Factories {
final FromBufferFactory fromBuffer;
final FromJsonFactory fromJson;
static Factories forMessage(String name) =>
_factories[name] ?? (throw 'Unsupported message: $name');
/// Mapping between [BenchmarkProto.messageName] and corresponding
/// deserialization factories.
static final _factories = {
'benchmarks.proto2.GoogleMessage1': Factories._(
fromBuffer: (List<int> binary) => p2.GoogleMessage1.fromBuffer(binary),
fromJson: (String json) => p2.GoogleMessage1.fromJson(json)),
'benchmarks.proto3.GoogleMessage1': Factories._(
fromBuffer: (List<int> binary) => p3.GoogleMessage1.fromBuffer(binary),
fromJson: (String json) => p3.GoogleMessage1.fromJson(json)),
'benchmarks.proto2.GoogleMessage2': Factories._(
fromBuffer: (List<int> binary) => GoogleMessage2.fromBuffer(binary),
fromJson: (String json) => GoogleMessage2.fromJson(json)),
'benchmarks.google_message3.GoogleMessage3': Factories._(
fromBuffer: (List<int> binary) => GoogleMessage3.fromBuffer(binary),
fromJson: (String json) => GoogleMessage3.fromJson(json)),
'benchmarks.google_message4.GoogleMessage4': Factories._(
fromBuffer: (List<int> binary) => GoogleMessage4.fromBuffer(binary),
fromJson: (String json) => GoogleMessage4.fromJson(json)),
};
Factories._({this.fromBuffer, this.fromJson});
}
/// Base for all protobuf benchmarks.
abstract class _ProtobufBenchmark extends BenchmarkBase {
final List<Dataset> datasets;
_ProtobufBenchmark(this.datasets, String name) : super(name);
}
/// Binary deserialization benchmark.
class FromBinaryBenchmark extends _ProtobufBenchmark {
FromBinaryBenchmark(datasets) : super(datasets, 'FromBinary');
@override
void run() {
for (var i = 0; i < datasets.length; i++) {
final ds = datasets[i];
final f = ds.factories.fromBuffer;
for (var j = 0; j < ds.packed.length; j++) {
f(ds.packed[j]);
}
}
}
}
/// Binary serialization benchmark.
class ToBinaryBenchmark extends _ProtobufBenchmark {
ToBinaryBenchmark(datasets) : super(datasets, 'ToBinary');
@override
void run() {
for (var i = 0; i < datasets.length; i++) {
final ds = datasets[i];
for (var j = 0; j < ds.unpacked.length; j++) {
ds.unpacked[j].writeToBuffer();
}
}
}
}
/// JSON deserialization benchmark.
class FromJsonBenchmark extends _ProtobufBenchmark {
FromJsonBenchmark(datasets) : super(datasets, 'FromJson');
@override
void run() {
for (var i = 0; i < datasets.length; i++) {
final ds = datasets[i];
final f = ds.factories.fromJson;
for (var j = 0; j < ds.asJson.length; j++) {
f(ds.asJson[j]);
}
}
}
}
/// JSON serialization benchmark.
class ToJsonBenchmark extends _ProtobufBenchmark {
ToJsonBenchmark(datasets) : super(datasets, 'ToJson');
@override
void run() {
for (var i = 0; i < datasets.length; i++) {
final ds = datasets[i];
for (var j = 0; j < ds.unpacked.length; j++) {
ds.unpacked[j].writeToJson();
}
}
}
}