0a88f4ef73
Removed from `benchmarks/`, `runtime/`, `sdk/`, `tools/` and `utils/`. (Leaving `tests/`, `pkg/` and `third_party/`.) CoreLibraryReviewExempt: No real change. Tested: No test changes for no real code changes. Change-Id: Ieb42441457ca3d0ea4443dd153ee902ea33b28de Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/480241 Commit-Queue: Lasse Nielsen <lrn@google.com> Reviewed-by: Ben Konyi <bkonyi@google.com> Reviewed-by: Nate Bosch <nbosch@google.com>
167 lines
4.6 KiB
Dart
167 lines
4.6 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.
|
|
|
|
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;
|
|
|
|
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(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 as Map;
|
|
port.close();
|
|
return decodedJson;
|
|
}
|
|
|
|
Future<void> jsonDecodingIsolate(JsonDecodeRequest request) async {
|
|
final result = json.decode(utf8.decode(request.encodedJson));
|
|
if (request.useSendAndExit) {
|
|
Isolate.exit(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/dart/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();
|
|
}
|
|
}
|
|
}
|