Files
sdk/benchmarks/IsolateSpawn/dart/IsolateSpawn.dart
T
Alexander Aprelev 208f3709b9 [vm/benchmark] Add IsolateSpawnMemory.Dart2JSDeltaRss benchmarks.
These new benchmarks better measure rss delta associated with spawning new dart2js isolate.

Also this moves IsolateSpawn heap measurement benchmarks into this group as well because
they are effectively new benchmarks.

Change-Id: Idf31f83b24713932d5ddfa096e23f36ae8195cd2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/123685
Commit-Queue: Alexander Aprelev <aam@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2019-11-04 23:53:05 +00:00

166 lines
5.1 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:isolate';
import 'dart:math';
import 'package:meta/meta.dart';
import 'package:compiler/src/dart2js.dart' as dart2js_main;
class SpawnLatency {
SpawnLatency(this.name);
Future<ResultMessageLatency> run() async {
final completerResult = Completer();
final receivePort = ReceivePort()..listen(completerResult.complete);
final Completer<DateTime> isolateExitedCompleter = Completer<DateTime>();
final onExitReceivePort = ReceivePort()
..listen((_) {
isolateExitedCompleter.complete(DateTime.now());
});
final DateTime beforeSpawn = DateTime.now();
await Isolate.spawn(
isolateCompiler, StartMessageLatency(receivePort.sendPort, beforeSpawn),
onExit: onExitReceivePort.sendPort,
onError: onExitReceivePort.sendPort);
final DateTime afterSpawn = DateTime.now();
final ResultMessageLatency result = await completerResult.future;
receivePort.close();
final DateTime isolateExited = await isolateExitedCompleter.future;
result.timeToExitUs = isolateExited.difference(beforeSpawn).inMicroseconds;
result.timeToIsolateSpawnUs =
afterSpawn.difference(beforeSpawn).inMicroseconds;
onExitReceivePort.close();
return result;
}
Future<AggregatedResultMessageLatency> measureFor(int minimumMillis) async {
final minimumMicros = minimumMillis * 1000;
final watch = Stopwatch()..start();
final Metric toAfterIsolateSpawnUs = LatencyMetric("${name}ToAfterSpawn");
final Metric toStartRunningCodeUs = LatencyMetric("${name}ToStartRunning");
final Metric toFinishRunningCodeUs =
LatencyMetric("${name}ToFinishRunning");
final Metric toExitUs = LatencyMetric("${name}ToExit");
while (watch.elapsedMicroseconds < minimumMicros) {
final ResultMessageLatency result = await run();
toAfterIsolateSpawnUs.add(result.timeToIsolateSpawnUs);
toStartRunningCodeUs.add(result.timeToStartRunningCodeUs);
toFinishRunningCodeUs.add(result.timeToFinishRunningCodeUs);
toExitUs.add(result.timeToExitUs);
}
return AggregatedResultMessageLatency(toAfterIsolateSpawnUs,
toStartRunningCodeUs, toFinishRunningCodeUs, toExitUs);
}
Future<AggregatedResultMessageLatency> measure() async {
await measureFor(500); // warm-up
return measureFor(4000); // actual measurement
}
Future<void> report() async {
final AggregatedResultMessageLatency result = await measure();
print(result);
}
final String name;
RawReceivePort receivePort;
}
class Metric {
Metric({@required this.prefix, @required this.suffix});
void add(int value) {
if (value > max) {
max = value;
}
sum += value;
sumOfSquares += value * value;
count++;
}
double _average() => sum / count;
double _rms() => sqrt(sumOfSquares / count);
toString() => "$prefix): ${_average()}$suffix\n"
"${prefix}Max): $max$suffix\n"
"${prefix}RMS): ${_rms()}$suffix";
final String prefix;
final String suffix;
int max = 0;
double sum = 0;
double sumOfSquares = 0;
int count = 0;
}
class LatencyMetric extends Metric {
LatencyMetric(String name) : super(prefix: "$name(Latency", suffix: " us.");
}
class StartMessageLatency {
StartMessageLatency(this.sendPort, this.spawned);
final SendPort sendPort;
final DateTime spawned;
}
class ResultMessageLatency {
ResultMessageLatency(
{this.timeToStartRunningCodeUs,
this.timeToFinishRunningCodeUs,
this.deltaHeap});
final int timeToStartRunningCodeUs;
final int timeToFinishRunningCodeUs;
final int deltaHeap;
int timeToIsolateSpawnUs;
int timeToExitUs;
}
class AggregatedResultMessageLatency {
AggregatedResultMessageLatency(
this.toAfterIsolateSpawnUs,
this.toStartRunningCodeUs,
this.toFinishRunningCodeUs,
this.toExitUs,
);
String toString() => """$toAfterIsolateSpawnUs
$toStartRunningCodeUs
$toFinishRunningCodeUs
$toExitUs""";
final Metric toAfterIsolateSpawnUs;
final Metric toStartRunningCodeUs;
final Metric toFinishRunningCodeUs;
final Metric toExitUs;
}
Future<void> isolateCompiler(StartMessageLatency start) async {
final DateTime timeRunningCodeUs = DateTime.now();
await runZoned(
() => dart2js_main.internalMain(<String>[
"benchmarks/IsolateSpawn/dart/helloworld.dart",
'--libraries-spec=sdk/lib/libraries.json'
]),
zoneSpecification: ZoneSpecification(
print: (Zone self, ZoneDelegate parent, Zone zone, String line) {}));
final DateTime timeFinishRunningCodeUs = DateTime.now();
start.sendPort.send(ResultMessageLatency(
timeToStartRunningCodeUs:
timeRunningCodeUs.difference(start.spawned).inMicroseconds,
timeToFinishRunningCodeUs:
timeFinishRunningCodeUs.difference(start.spawned).inMicroseconds));
}
Future<void> main() async {
await SpawnLatency("IsolateSpawn.Dart2JS").report();
}