2019-11-04 23:53:05 +00:00
|
|
|
// 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:developer';
|
|
|
|
import 'dart:io';
|
|
|
|
import 'dart:isolate';
|
2019-12-03 12:07:55 +00:00
|
|
|
import 'dart:math' as math;
|
2019-11-04 23:53:05 +00:00
|
|
|
|
|
|
|
import 'package:compiler/src/dart2js.dart' as dart2js_main;
|
|
|
|
import 'package:vm_service/vm_service.dart' as vm_service;
|
|
|
|
import 'package:vm_service/vm_service_io.dart' as vm_service_io;
|
|
|
|
|
2019-12-03 12:07:55 +00:00
|
|
|
const String compilerIsolateName = 'isolate-compiler';
|
|
|
|
|
2019-11-04 23:53:05 +00:00
|
|
|
class Result {
|
|
|
|
const Result(
|
|
|
|
this.rssOnStart, this.rssOnEnd, this.heapOnStart, this.heapOnEnd);
|
|
|
|
|
|
|
|
final int rssOnStart;
|
|
|
|
final int rssOnEnd;
|
|
|
|
final int heapOnStart;
|
|
|
|
final int heapOnEnd;
|
|
|
|
}
|
|
|
|
|
|
|
|
class StartMessage {
|
2019-12-03 12:07:55 +00:00
|
|
|
const StartMessage(this.wsUri, this.sendPort);
|
2019-11-04 23:53:05 +00:00
|
|
|
|
|
|
|
final String wsUri;
|
|
|
|
final SendPort sendPort;
|
|
|
|
}
|
|
|
|
|
|
|
|
class SpawnMemory {
|
2019-12-03 12:07:55 +00:00
|
|
|
SpawnMemory(this.name, this.wsUri);
|
2019-11-04 23:53:05 +00:00
|
|
|
|
|
|
|
Future<void> report() async {
|
2019-12-03 12:07:55 +00:00
|
|
|
int maxProcessRss = 0;
|
|
|
|
final timer = Timer.periodic(const Duration(microseconds: 100), (_) {
|
|
|
|
maxProcessRss = math.max(maxProcessRss, ProcessInfo.currentRss);
|
|
|
|
});
|
|
|
|
|
|
|
|
const numberOfBenchmarks = 3;
|
|
|
|
|
|
|
|
final beforeRss = ProcessInfo.currentRss;
|
|
|
|
final beforeHeap = await currentHeapUsage(wsUri);
|
2019-11-04 23:53:05 +00:00
|
|
|
|
2019-12-03 12:07:55 +00:00
|
|
|
final iterators = <StreamIterator>[];
|
|
|
|
final continuations = <SendPort>[];
|
|
|
|
|
|
|
|
// Start all isolates & make them wait.
|
|
|
|
for (int i = 0; i < numberOfBenchmarks; i++) {
|
2019-11-04 23:53:05 +00:00
|
|
|
final receivePort = ReceivePort();
|
2019-12-03 12:07:55 +00:00
|
|
|
final startMessage = StartMessage(wsUri, receivePort.sendPort);
|
|
|
|
await Isolate.spawn(isolateCompiler, startMessage,
|
|
|
|
debugName: compilerIsolateName);
|
|
|
|
final iterator = StreamIterator(receivePort);
|
|
|
|
|
|
|
|
if (!await iterator.moveNext()) throw 'failed';
|
|
|
|
continuations.add(iterator.current as SendPort);
|
|
|
|
|
|
|
|
iterators.add(iterator);
|
|
|
|
}
|
|
|
|
|
|
|
|
final readyRss = ProcessInfo.currentRss;
|
|
|
|
final readyHeap = await currentHeapUsage(wsUri);
|
|
|
|
|
|
|
|
// Let all isolates do the dart2js compilation.
|
|
|
|
for (int i = 0; i < numberOfBenchmarks; i++) {
|
|
|
|
final iterator = iterators[i];
|
|
|
|
final continuation = continuations[i];
|
|
|
|
continuation.send(null);
|
|
|
|
if (!await iterator.moveNext()) throw 'failed';
|
|
|
|
if (iterator.current != 'done') throw 'failed';
|
|
|
|
}
|
|
|
|
|
|
|
|
final doneRss = ProcessInfo.currentRss;
|
|
|
|
final doneHeap = await currentHeapUsage(wsUri);
|
|
|
|
|
|
|
|
// Shut down helper isolates
|
|
|
|
for (int i = 0; i < numberOfBenchmarks; i++) {
|
|
|
|
final iterator = iterators[i];
|
|
|
|
final continuation = continuations[i];
|
|
|
|
continuation.send(null);
|
|
|
|
if (!await iterator.moveNext()) throw 'failed';
|
|
|
|
if (iterator.current != 'shutdown') throw 'failed';
|
|
|
|
await iterator.cancel();
|
2019-11-04 23:53:05 +00:00
|
|
|
}
|
2019-12-03 12:07:55 +00:00
|
|
|
timer.cancel();
|
|
|
|
|
|
|
|
final readyDiffRss =
|
|
|
|
math.max(0, readyRss - beforeRss) ~/ numberOfBenchmarks;
|
|
|
|
final readyDiffHeap =
|
|
|
|
math.max(0, readyHeap - beforeHeap) ~/ numberOfBenchmarks;
|
|
|
|
final doneDiffRss = math.max(0, doneRss - beforeRss) ~/ numberOfBenchmarks;
|
|
|
|
final doneDiffHeap =
|
|
|
|
math.max(0, doneHeap - beforeHeap) ~/ numberOfBenchmarks;
|
|
|
|
|
|
|
|
print("${name}RssOnStart(MemoryUse): $readyDiffRss");
|
|
|
|
print("${name}RssOnEnd(MemoryUse): $doneDiffRss");
|
|
|
|
print("${name}HeapOnStart(MemoryUse): $readyDiffHeap");
|
|
|
|
print("${name}HeapOnEnd(MemoryUse): $doneDiffHeap");
|
|
|
|
print("${name}PeakProcessRss(MemoryUse): $maxProcessRss");
|
2019-11-04 23:53:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
final String name;
|
|
|
|
final String wsUri;
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> isolateCompiler(StartMessage startMessage) async {
|
2019-12-03 12:07:55 +00:00
|
|
|
final port = ReceivePort();
|
|
|
|
final iterator = StreamIterator(port);
|
|
|
|
|
|
|
|
// Let main isolate know we're ready.
|
|
|
|
startMessage.sendPort.send(port.sendPort);
|
|
|
|
await iterator.moveNext();
|
|
|
|
|
2019-11-04 23:53:05 +00:00
|
|
|
await runZoned(
|
|
|
|
() => dart2js_main.internalMain(<String>[
|
|
|
|
"benchmarks/IsolateSpawnMemory/dart/helloworld.dart",
|
|
|
|
'--libraries-spec=sdk/lib/libraries.json'
|
|
|
|
]),
|
|
|
|
zoneSpecification: ZoneSpecification(
|
|
|
|
print: (Zone self, ZoneDelegate parent, Zone zone, String line) {}));
|
2019-12-03 12:07:55 +00:00
|
|
|
|
|
|
|
// Let main isolate know we're done.
|
|
|
|
startMessage.sendPort.send('done');
|
|
|
|
await iterator.moveNext();
|
|
|
|
|
|
|
|
// Closes the port.
|
|
|
|
startMessage.sendPort.send('shutdown');
|
|
|
|
await iterator.cancel();
|
2019-11-04 23:53:05 +00:00
|
|
|
}
|
|
|
|
|
2019-12-03 12:07:55 +00:00
|
|
|
Future<int> currentHeapUsage(String wsUri) async {
|
2019-11-04 23:53:05 +00:00
|
|
|
final vm_service.VmService vmService =
|
|
|
|
await vm_service_io.vmServiceConnectUri(wsUri);
|
2019-12-03 12:07:55 +00:00
|
|
|
final groupIds = await getGroupIds(vmService);
|
|
|
|
int sum = 0;
|
|
|
|
for (final groupId in groupIds) {
|
|
|
|
final vm_service.MemoryUsage usage =
|
|
|
|
await vmService.getIsolateGroupMemoryUsage(groupId);
|
|
|
|
sum += usage.heapUsage + usage.externalUsage;
|
|
|
|
}
|
2019-11-04 23:53:05 +00:00
|
|
|
vmService.dispose();
|
2019-12-03 12:07:55 +00:00
|
|
|
return sum;
|
2019-11-04 23:53:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> main() async {
|
2019-12-03 12:07:55 +00:00
|
|
|
// Only if we successfully reach the end will we set 0 exit code.
|
|
|
|
exitCode = 255;
|
|
|
|
|
2019-11-04 23:53:05 +00:00
|
|
|
final ServiceProtocolInfo info = await Service.controlWebServer(enable: true);
|
|
|
|
final Uri observatoryUri = info.serverUri;
|
|
|
|
final String wsUri =
|
|
|
|
'ws://${observatoryUri.authority}${observatoryUri.path}ws';
|
2019-12-03 12:07:55 +00:00
|
|
|
await SpawnMemory("IsolateSpawnMemory.Dart2JSDelta", wsUri).report();
|
2019-11-04 23:53:05 +00:00
|
|
|
|
2019-12-03 12:07:55 +00:00
|
|
|
// Only if we successfully reach the end will we set 0 exit code.
|
|
|
|
exitCode = 0;
|
2019-11-04 23:53:05 +00:00
|
|
|
}
|
|
|
|
|
2019-12-03 12:07:55 +00:00
|
|
|
// Returns the set of isolate groups for which we should count the heap usage.
|
|
|
|
//
|
|
|
|
// We have two cases
|
|
|
|
//
|
|
|
|
// a) --enable-isolate-groups: All isolates will be within the same isolate
|
|
|
|
// group.
|
|
|
|
//
|
|
|
|
// b) --no-enable-isolate-groups: All isolates will be within their own,
|
|
|
|
// separate isolate group.
|
|
|
|
//
|
|
|
|
// In both cases we want to sum up the heap sizes of all isolate groups.
|
|
|
|
Future<List<String>> getGroupIds(vm_service.VmService vmService) async {
|
|
|
|
final groupIds = <String>{};
|
2019-11-04 23:53:05 +00:00
|
|
|
final vm = await vmService.getVM();
|
|
|
|
for (vm_service.IsolateGroupRef groupRef in vm.isolateGroups) {
|
|
|
|
final vm_service.IsolateGroup group =
|
|
|
|
await vmService.getIsolateGroup(groupRef.id);
|
|
|
|
for (vm_service.IsolateRef isolateRef in group.isolates) {
|
|
|
|
final isolateOrSentinel = await vmService.getIsolate(isolateRef.id);
|
|
|
|
if (isolateOrSentinel is vm_service.Isolate) {
|
2019-12-03 12:07:55 +00:00
|
|
|
groupIds.add(groupRef.id);
|
2019-11-04 23:53:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-12-03 12:07:55 +00:00
|
|
|
if (groupIds.isEmpty) {
|
|
|
|
throw "Could not find main isolate";
|
|
|
|
}
|
|
|
|
return groupIds.toList();
|
2019-11-04 23:53:05 +00:00
|
|
|
}
|