80621fed03
Change-Id: I44047a9d7907d166a6360397d0047ce9b835e5c7 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/166854 Auto-Submit: Jonas Termansen <sortie@google.com> Reviewed-by: Leaf Petersen <leafp@google.com> Commit-Queue: Leaf Petersen <leafp@google.com>
164 lines
4.8 KiB
Dart
164 lines
4.8 KiB
Dart
// Copyright (c) 2019, 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.
|
|
|
|
// @dart=2.9
|
|
|
|
import 'dart:async';
|
|
import 'dart:convert';
|
|
import 'dart:io';
|
|
import 'dart:isolate';
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:benchmark_harness/benchmark_harness.dart' show BenchmarkBase;
|
|
import 'package:meta/meta.dart';
|
|
|
|
import 'runtime/tests/vm/dart/export_sendAndExit_helper.dart' show sendAndExit;
|
|
|
|
class JsonDecodingBenchmark {
|
|
JsonDecodingBenchmark(this.name,
|
|
{@required this.sample,
|
|
@required this.numTasks,
|
|
@required this.useSendAndExit});
|
|
|
|
Future<void> report() async {
|
|
final stopwatch = Stopwatch()..start();
|
|
// Benchmark harness counts 10 iterations as one.
|
|
for (int i = 0; i < 10; i++) {
|
|
final decodedFutures = <Future>[];
|
|
for (int i = 0; i < numTasks; i++) {
|
|
decodedFutures.add(decodeJson(useSendAndExit, sample));
|
|
}
|
|
await Future.wait(decodedFutures);
|
|
}
|
|
|
|
print('$name(RunTime): ${stopwatch.elapsedMicroseconds} us.');
|
|
}
|
|
|
|
final String name;
|
|
final Uint8List sample;
|
|
final int numTasks;
|
|
final bool useSendAndExit;
|
|
}
|
|
|
|
Uint8List createSampleJson(final size) {
|
|
final list = List.generate(size, (i) => i);
|
|
final map = <dynamic, dynamic>{};
|
|
for (int i = 0; i < size; i++) {
|
|
map['$i'] = list;
|
|
}
|
|
return utf8.encode(json.encode(map));
|
|
}
|
|
|
|
class JsonDecodeRequest {
|
|
final bool useSendAndExit;
|
|
final SendPort sendPort;
|
|
final Uint8List encodedJson;
|
|
const JsonDecodeRequest(this.useSendAndExit, this.sendPort, this.encodedJson);
|
|
}
|
|
|
|
Future<Map> decodeJson(bool useSendAndExit, Uint8List encodedJson) async {
|
|
final port = ReceivePort();
|
|
final inbox = StreamIterator<dynamic>(port);
|
|
final completer = Completer<bool>();
|
|
final workerExitedPort = RawReceivePort((v) {
|
|
completer.complete(true);
|
|
});
|
|
final workerErroredPort = RawReceivePort((v) {
|
|
stderr.writeln('worker errored out $v');
|
|
completer.completeError(true);
|
|
});
|
|
await Isolate.spawn(jsonDecodingIsolate,
|
|
JsonDecodeRequest(useSendAndExit, port.sendPort, encodedJson),
|
|
onError: workerErroredPort.sendPort, onExit: workerExitedPort.sendPort);
|
|
await completer.future;
|
|
workerExitedPort.close();
|
|
workerErroredPort.close();
|
|
await inbox.moveNext();
|
|
final decodedJson = inbox.current;
|
|
port.close();
|
|
return decodedJson;
|
|
}
|
|
|
|
Future<void> jsonDecodingIsolate(JsonDecodeRequest request) async {
|
|
final result = json.decode(utf8.decode(request.encodedJson));
|
|
if (request.useSendAndExit) {
|
|
sendAndExit(request.sendPort, result);
|
|
} else {
|
|
request.sendPort.send(result);
|
|
}
|
|
}
|
|
|
|
class SyncJsonDecodingBenchmark extends BenchmarkBase {
|
|
SyncJsonDecodingBenchmark(String name,
|
|
{@required this.sample, @required this.iterations})
|
|
: super(name);
|
|
|
|
@override
|
|
void run() {
|
|
int l = 0;
|
|
for (int i = 0; i < iterations; i++) {
|
|
final Map map = json.decode(utf8.decode(sample));
|
|
l += map.length;
|
|
}
|
|
assert(l > 0);
|
|
}
|
|
|
|
final Uint8List sample;
|
|
final int iterations;
|
|
}
|
|
|
|
class BenchmarkConfig {
|
|
BenchmarkConfig(this.suffix, this.sample);
|
|
|
|
final String suffix;
|
|
final Uint8List sample;
|
|
}
|
|
|
|
Future<void> main() async {
|
|
final jsonString =
|
|
File('benchmarks/IsolateJson/dart2/sample.json').readAsStringSync();
|
|
final json250KB = utf8.encode(jsonString); // 294356 bytes
|
|
final decoded = json.decode(utf8.decode(json250KB));
|
|
final decoded1MB = <dynamic, dynamic>{
|
|
'1': decoded['1'],
|
|
'2': decoded['1'],
|
|
'3': decoded['1'],
|
|
'4': decoded['1'],
|
|
};
|
|
final json1MB = utf8.encode(json.encode(decoded1MB)); // 1177397 bytes
|
|
decoded['1'] = (decoded['1'] as List).sublist(0, 200);
|
|
final json100KB = utf8.encode(json.encode(decoded)); // 104685 bytes
|
|
decoded['1'] = (decoded['1'] as List).sublist(0, 100);
|
|
final json50KB = utf8.encode(json.encode(decoded)); // 51760 bytes
|
|
|
|
final configs = <BenchmarkConfig>[
|
|
BenchmarkConfig('50KB', json50KB),
|
|
BenchmarkConfig('100KB', json100KB),
|
|
BenchmarkConfig('250KB', json250KB),
|
|
BenchmarkConfig('1MB', json1MB),
|
|
];
|
|
|
|
for (final config in configs) {
|
|
for (final iterations in <int>[1, 4]) {
|
|
await JsonDecodingBenchmark(
|
|
'IsolateJson.Decode${config.suffix}x$iterations',
|
|
useSendAndExit: false,
|
|
sample: config.sample,
|
|
numTasks: iterations)
|
|
.report();
|
|
await JsonDecodingBenchmark(
|
|
'IsolateJson.SendAndExit_Decode${config.suffix}x$iterations',
|
|
useSendAndExit: true,
|
|
sample: config.sample,
|
|
numTasks: iterations)
|
|
.report();
|
|
SyncJsonDecodingBenchmark(
|
|
'IsolateJson.SyncDecode${config.suffix}x$iterations',
|
|
sample: config.sample,
|
|
iterations: iterations)
|
|
.report();
|
|
}
|
|
}
|
|
}
|