1
0
mirror of https://github.com/dart-lang/sdk synced 2024-07-05 09:20:04 +00:00
dart-sdk/benchmarks/IsolateSpawnMemory/dart/IsolateSpawnMemory.dart
Jacob Richman 933537b66b Trivial cleanup to make VSCode workspace for the SDK
free of diagnostics as long as you filter with "!TODO"

R=athom@google.com, jensj@google.com, natebiggs@google.com

Change-Id: I73cf3c5ef6dab81808330c4eb5f44cb62e753c81
Tested: manually verified that VSCode is warning free. No changes in functionality.
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/333903
Auto-Submit: Jacob Richman <jacobr@google.com>
Reviewed-by: Alexander Thomas <athom@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Nate Biggs <natebiggs@google.com>
Commit-Queue: Jacob Richman <jacobr@google.com>
2023-11-07 17:49:53 +00:00

182 lines
5.7 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:developer';
import 'dart:io';
import 'dart:isolate';
import 'dart:math' as math;
import 'package:vm_service/vm_service.dart' as vm_service;
import 'package:vm_service/vm_service_io.dart' as vm_service_io;
import '../../../pkg/vm/bin/gen_kernel.dart' as gen_kernel;
const String compilerIsolateName = 'isolate-compiler';
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.sendPort);
final String wsUri;
final SendPort sendPort;
}
class SpawnMemory {
SpawnMemory(this.name, this.wsUri);
Future<void> report() async {
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);
final iterators = <StreamIterator>[];
final continuations = <SendPort>[];
// Start all isolates & make them wait.
for (int i = 0; i < numberOfBenchmarks; i++) {
final receivePort = ReceivePort();
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 gen_kernel 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();
}
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');
}
final String name;
final String wsUri;
}
Future<void> isolateCompiler(StartMessage startMessage) async {
final port = ReceivePort();
final iterator = StreamIterator(port);
// Let main isolate know we're ready.
startMessage.sendPort.send(port.sendPort);
await iterator.moveNext();
await runZoned(
() => gen_kernel.compile(<String>[
'benchmarks/IsolateSpawn/dart/helloworld.dart',
'benchmarks/IsolateSpawn/dart/helloworld.dart.dill',
]),
zoneSpecification: ZoneSpecification(
print: (Zone self, ZoneDelegate parent, Zone zone, String line) {}));
// Let main isolate know we're done.
startMessage.sendPort.send('done');
await iterator.moveNext();
// Closes the port.
startMessage.sendPort.send('shutdown');
await iterator.cancel();
}
Future<int> currentHeapUsage(String wsUri) async {
final vmService = await vm_service_io.vmServiceConnectUri(wsUri);
final groupIds = await getGroupIds(vmService);
int sum = 0;
for (final groupId in groupIds) {
final usage = await vmService.getIsolateGroupMemoryUsage(groupId);
sum += usage.heapUsage! + usage.externalUsage!;
}
unawaited(vmService.dispose());
return sum;
}
Future<void> main() async {
// Only if we successfully reach the end will we set 0 exit code.
exitCode = 255;
final info = await Service.controlWebServer(enable: true);
final observatoryUri = info.serverUri!;
final wsUri = 'ws://${observatoryUri.authority}${observatoryUri.path}ws';
await SpawnMemory('IsolateSpawnMemory.Dart2JSDelta', wsUri).report();
// Only if we successfully reach the end will we set 0 exit code.
exitCode = 0;
}
// Returns the set of isolate groups for which we should count the heap usage.
Future<List<String>> getGroupIds(vm_service.VmService vmService) async {
final groupIds = <String>{};
final vm = await vmService.getVM();
for (final groupRef in vm.isolateGroups!) {
final group = await vmService.getIsolateGroup(groupRef.id!);
for (final isolateRef in group.isolates!) {
try {
await vmService.getIsolate(isolateRef.id!);
groupIds.add(groupRef.id!);
break;
} on vm_service.SentinelException catch (_) {
// Skip groups with only sentinels.
}
}
}
if (groupIds.isEmpty) {
throw 'Could not find main isolate';
}
return groupIds.toList();
}