blob: 796987785ce412bb0937b7c3e5e1284542798319 [file] [log] [blame]
// 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';
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;
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 {
const StartMessage(this.wsUri, this.groupRefId, this.sendPort);
final String wsUri;
final String groupRefId;
final SendPort sendPort;
}
class SpawnMemory {
SpawnMemory(this.name, this.wsUri, this.groupRefId);
Future<void> report() async {
const numberOfRuns = 3;
int sumDeltaRssOnStart = 0;
int sumDeltaRssOnEnd = 0;
int sumDeltaHeapOnStart = 0;
int sumDeltaHeapOnEnd = 0;
for (int i = 0; i < numberOfRuns; i++) {
final receivePort = ReceivePort();
final beforeRss = ProcessInfo.currentRss;
final beforeHeap = await currentHeapUsage(wsUri, groupRefId);
final startMessage =
StartMessage(wsUri, groupRefId, receivePort.sendPort);
await Isolate.spawn(isolateCompiler, startMessage);
final Result result = await receivePort.first;
sumDeltaRssOnStart += result.rssOnStart - beforeRss;
sumDeltaRssOnEnd += result.rssOnEnd - beforeRss;
sumDeltaHeapOnStart += result.heapOnStart - beforeHeap;
sumDeltaHeapOnEnd += result.heapOnEnd - beforeHeap;
}
print(
"${name}RssOnStart(MemoryUse): ${sumDeltaRssOnStart ~/ numberOfRuns}");
print("${name}RssOnEnd(MemoryUse): ${sumDeltaRssOnEnd ~/ numberOfRuns}");
print(
"${name}HeapOnStart(MemoryUse): ${sumDeltaHeapOnStart ~/ numberOfRuns}");
print("${name}HeapOnEnd(MemoryUse): ${sumDeltaHeapOnEnd ~/ numberOfRuns}");
}
final String name;
final String wsUri;
final String groupRefId;
RawReceivePort receivePort;
}
Future<void> isolateCompiler(StartMessage startMessage) async {
final rssOnStart = ProcessInfo.currentRss;
final heapOnStart =
await currentHeapUsage(startMessage.wsUri, startMessage.groupRefId);
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) {}));
startMessage.sendPort.send(Result(
rssOnStart,
ProcessInfo.currentRss,
heapOnStart,
await currentHeapUsage(startMessage.wsUri, startMessage.groupRefId)));
ReceivePort(); // prevent isolate from exiting to ensure Rss monotonically grows
}
Future<int> currentHeapUsage(String wsUri, String groupRefId) async {
final vm_service.VmService vmService =
await vm_service_io.vmServiceConnectUri(wsUri);
final vm_service.MemoryUsage usage =
await vmService.getIsolateGroupMemoryUsage(groupRefId);
vmService.dispose();
return usage.heapUsage + usage.externalUsage;
}
Future<void> main() async {
final ServiceProtocolInfo info = await Service.controlWebServer(enable: true);
final Uri observatoryUri = info.serverUri;
final String wsUri =
'ws://${observatoryUri.authority}${observatoryUri.path}ws';
final vm_service.VmService vmService =
await vm_service_io.vmServiceConnectUri(wsUri);
final String mainGroupRefId = await getMainGroupRefId(vmService);
vmService.dispose();
await SpawnMemory("IsolateSpawnMemory.Dart2JSDelta", wsUri, mainGroupRefId)
.report();
}
Future<String> getMainGroupRefId(vm_service.VmService vmService) async {
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) {
final vm_service.Isolate isolate = isolateOrSentinel;
if (isolate.name == 'main') {
return groupRef.id;
}
}
}
}
throw "Could not find main isolate";
}