Skip to content

Commit f219e51

Browse files
aamcommit-bot@chromium.org
authored and
commit-bot@chromium.org
committed
[vm/service] Introduce IsolateGroup entity to vm service api.
This is to enable vm clients to ask how much memory is consumed by isolate group. Issue #36097 Change-Id: I4f1c499bf02c20b80e9802d8ad60e7ea65cfb375 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/119724 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
1 parent 2c94e56 commit f219e51

29 files changed

+906
-48
lines changed

pkg/vm_service/example/vm_service_assert.dart

+28
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,33 @@ vms.Isolate assertIsolate(vms.Isolate obj) {
672672
return obj;
673673
}
674674

675+
vms.IsolateGroupRef assertIsolateGroupRef(vms.IsolateGroupRef obj) {
676+
assertNotNull(obj);
677+
assertString(obj.type);
678+
assertString(obj.id);
679+
assertString(obj.number);
680+
assertString(obj.name);
681+
return obj;
682+
}
683+
684+
List<vms.IsolateGroupRef> assertListOfIsolateGroupRef(
685+
List<vms.IsolateGroupRef> list) {
686+
for (vms.IsolateGroupRef elem in list) {
687+
assertIsolateGroupRef(elem);
688+
}
689+
return list;
690+
}
691+
692+
vms.IsolateGroup assertIsolateGroup(vms.IsolateGroup obj) {
693+
assertNotNull(obj);
694+
assertString(obj.type);
695+
assertString(obj.id);
696+
assertString(obj.number);
697+
assertString(obj.name);
698+
assertListOfIsolateRef(obj.isolates);
699+
return obj;
700+
}
701+
675702
vms.InboundReferences assertInboundReferences(vms.InboundReferences obj) {
676703
assertNotNull(obj);
677704
assertString(obj.type);
@@ -1108,5 +1135,6 @@ vms.VM assertVM(vms.VM obj) {
11081135
assertInt(obj.pid);
11091136
assertInt(obj.startTime);
11101137
assertListOfIsolateRef(obj.isolates);
1138+
assertListOfIsolateGroupRef(obj.isolateGroups);
11111139
return obj;
11121140
}

pkg/vm_service/java/.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ src/org/dartlang/vm/service/consumer/EvaluateInFrameConsumer.java
99
src/org/dartlang/vm/service/consumer/FlagListConsumer.java
1010
src/org/dartlang/vm/service/consumer/GetInboundReferencesConsumer.java
1111
src/org/dartlang/vm/service/consumer/GetIsolateConsumer.java
12+
src/org/dartlang/vm/service/consumer/GetIsolateGroupConsumer.java
13+
src/org/dartlang/vm/service/consumer/GetIsolateGroupMemoryUsageConsumer.java
1214
src/org/dartlang/vm/service/consumer/GetMemoryUsageConsumer.java
1315
src/org/dartlang/vm/service/consumer/GetObjectConsumer.java
1416
src/org/dartlang/vm/service/consumer/InstanceSetConsumer.java
@@ -63,6 +65,8 @@ src/org/dartlang/vm/service/element/InstanceKind.java
6365
src/org/dartlang/vm/service/element/InstanceRef.java
6466
src/org/dartlang/vm/service/element/InstanceSet.java
6567
src/org/dartlang/vm/service/element/Isolate.java
68+
src/org/dartlang/vm/service/element/IsolateGroup.java
69+
src/org/dartlang/vm/service/element/IsolateGroupRef.java
6670
src/org/dartlang/vm/service/element/IsolateRef.java
6771
src/org/dartlang/vm/service/element/Library.java
6872
src/org/dartlang/vm/service/element/LibraryDependency.java

pkg/vm_service/lib/vm_service.dart

+158
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ Map<String, Function> _typeFactories = {
131131
'Instance': Instance.parse,
132132
'@Isolate': IsolateRef.parse,
133133
'Isolate': Isolate.parse,
134+
'@IsolateGroup': IsolateGroupRef.parse,
135+
'IsolateGroup': IsolateGroup.parse,
134136
'InboundReferences': InboundReferences.parse,
135137
'InboundReference': InboundReference.parse,
136138
'InstanceSet': InstanceSet.parse,
@@ -188,7 +190,9 @@ Map<String, List<String>> _methodReturnTypes = {
188190
'getInboundReferences': const ['InboundReferences', 'Sentinel'],
189191
'getInstances': const ['InstanceSet'],
190192
'getIsolate': const ['Isolate', 'Sentinel'],
193+
'getIsolateGroup': const ['IsolateGroup', 'Sentinel'],
191194
'getMemoryUsage': const ['MemoryUsage', 'Sentinel'],
195+
'getIsolateGroupMemoryUsage': const ['MemoryUsage', 'Sentinel'],
192196
'getScripts': const ['ScriptList'],
193197
'getObject': const ['Obj', 'Sentinel'],
194198
'getRetainingPath': const ['RetainingPath'],
@@ -506,6 +510,21 @@ abstract class VmServiceInterface {
506510
/// The return value can be one of [Isolate] or [Sentinel].
507511
Future<dynamic> getIsolate(String isolateId);
508512

513+
/// The `getIsolateGroup` RPC is used to lookup an `IsolateGroup` object by
514+
/// its `id`.
515+
///
516+
/// If `isolateGroupId` refers to an isolate group which has exited, then the
517+
/// `Expired` [Sentinel] is returned.
518+
///
519+
/// `IsolateGroup` `id` is an opaque identifier that can be fetched from an
520+
/// `IsolateGroup`. List of active `IsolateGroup`'s, for example, is available
521+
/// on `VM` object.
522+
///
523+
/// See [IsolateGroup], [VM].
524+
///
525+
/// The return value can be one of [IsolateGroup] or [Sentinel].
526+
Future<dynamic> getIsolateGroup(String isolateGroupId);
527+
509528
/// The `getMemoryUsage` RPC is used to lookup an isolate's memory usage
510529
/// statistics by its `id`.
511530
///
@@ -517,6 +536,17 @@ abstract class VmServiceInterface {
517536
/// The return value can be one of [MemoryUsage] or [Sentinel].
518537
Future<dynamic> getMemoryUsage(String isolateId);
519538

539+
/// The `getIsolateGroupMemoryUsage` RPC is used to lookup an isolate group's
540+
/// memory usage statistics by its `id`.
541+
///
542+
/// If `isolateGroupId` refers to an isolate group which has exited, then the
543+
/// `Expired` [Sentinel] is returned.
544+
///
545+
/// See [IsolateGroup].
546+
///
547+
/// The return value can be one of [MemoryUsage] or [Sentinel].
548+
Future<dynamic> getIsolateGroupMemoryUsage(String isolateGroupId);
549+
520550
/// The `getScripts` RPC is used to retrieve a `ScriptList` containing all
521551
/// scripts for an isolate based on the isolate's `isolateId`.
522552
///
@@ -1027,11 +1057,21 @@ class VmServerConnection {
10271057
params['isolateId'],
10281058
);
10291059
break;
1060+
case 'getIsolateGroup':
1061+
response = await _serviceImplementation.getIsolateGroup(
1062+
params['isolateGroupId'],
1063+
);
1064+
break;
10301065
case 'getMemoryUsage':
10311066
response = await _serviceImplementation.getMemoryUsage(
10321067
params['isolateId'],
10331068
);
10341069
break;
1070+
case 'getIsolateGroupMemoryUsage':
1071+
response = await _serviceImplementation.getIsolateGroupMemoryUsage(
1072+
params['isolateGroupId'],
1073+
);
1074+
break;
10351075
case 'getScripts':
10361076
response = await _serviceImplementation.getScripts(
10371077
params['isolateId'],
@@ -1468,11 +1508,22 @@ class VmService implements VmServiceInterface {
14681508
return _call('getIsolate', {'isolateId': isolateId});
14691509
}
14701510

1511+
@override
1512+
Future<dynamic> getIsolateGroup(String isolateGroupId) {
1513+
return _call('getIsolateGroup', {'isolateGroupId': isolateGroupId});
1514+
}
1515+
14711516
@override
14721517
Future<dynamic> getMemoryUsage(String isolateId) {
14731518
return _call('getMemoryUsage', {'isolateId': isolateId});
14741519
}
14751520

1521+
@override
1522+
Future<dynamic> getIsolateGroupMemoryUsage(String isolateGroupId) {
1523+
return _call(
1524+
'getIsolateGroupMemoryUsage', {'isolateGroupId': isolateGroupId});
1525+
}
1526+
14761527
@override
14771528
Future<ScriptList> getScripts(String isolateId) {
14781529
return _call('getScripts', {'isolateId': isolateId});
@@ -1699,6 +1750,7 @@ class VmService implements VmServiceInterface {
16991750
void dispose() {
17001751
_streamSub.cancel();
17011752
_completers.values.forEach((c) => c.completeError('disposed'));
1753+
_completers.clear();
17021754
if (_disposeHandler != null) {
17031755
_disposeHandler();
17041756
}
@@ -4444,6 +4496,105 @@ class Isolate extends Response {
44444496
String toString() => '[Isolate]';
44454497
}
44464498

4499+
/// `IsolateGroupRef` is a reference to an `IsolateGroup` object.
4500+
class IsolateGroupRef extends Response {
4501+
static IsolateGroupRef parse(Map<String, dynamic> json) =>
4502+
json == null ? null : IsolateGroupRef._fromJson(json);
4503+
4504+
/// The id which is passed to the getIsolateGroup RPC to load this isolate
4505+
/// group.
4506+
String id;
4507+
4508+
/// A numeric id for this isolate group, represented as a string. Unique.
4509+
String number;
4510+
4511+
/// A name identifying this isolate group. Not guaranteed to be unique.
4512+
String name;
4513+
4514+
IsolateGroupRef({
4515+
@required this.id,
4516+
@required this.number,
4517+
@required this.name,
4518+
});
4519+
IsolateGroupRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
4520+
id = json['id'];
4521+
number = json['number'];
4522+
name = json['name'];
4523+
}
4524+
4525+
@override
4526+
Map<String, dynamic> toJson() {
4527+
var json = <String, dynamic>{};
4528+
json['type'] = '@IsolateGroup';
4529+
json.addAll({
4530+
'id': id,
4531+
'number': number,
4532+
'name': name,
4533+
});
4534+
return json;
4535+
}
4536+
4537+
int get hashCode => id.hashCode;
4538+
4539+
operator ==(other) => other is IsolateGroupRef && id == other.id;
4540+
4541+
String toString() =>
4542+
'[IsolateGroupRef type: ${type}, id: ${id}, number: ${number}, name: ${name}]';
4543+
}
4544+
4545+
/// An `Isolate` object provides information about one isolate in the VM.
4546+
class IsolateGroup extends Response {
4547+
static IsolateGroup parse(Map<String, dynamic> json) =>
4548+
json == null ? null : IsolateGroup._fromJson(json);
4549+
4550+
/// The id which is passed to the getIsolate RPC to reload this isolate.
4551+
String id;
4552+
4553+
/// A numeric id for this isolate, represented as a string. Unique.
4554+
String number;
4555+
4556+
/// A name identifying this isolate. Not guaranteed to be unique.
4557+
String name;
4558+
4559+
/// A list of all isolates in this isolate group.
4560+
List<IsolateRef> isolates;
4561+
4562+
IsolateGroup({
4563+
@required this.id,
4564+
@required this.number,
4565+
@required this.name,
4566+
@required this.isolates,
4567+
});
4568+
IsolateGroup._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
4569+
id = json['id'];
4570+
number = json['number'];
4571+
name = json['name'];
4572+
isolates = List<IsolateRef>.from(
4573+
createServiceObject(json['isolates'], const ['IsolateRef']));
4574+
}
4575+
4576+
@override
4577+
Map<String, dynamic> toJson() {
4578+
var json = <String, dynamic>{};
4579+
json['type'] = 'IsolateGroup';
4580+
json.addAll({
4581+
'id': id,
4582+
'number': number,
4583+
'name': name,
4584+
'isolates': isolates.map((f) => f.toJson()).toList(),
4585+
});
4586+
return json;
4587+
}
4588+
4589+
int get hashCode => id.hashCode;
4590+
4591+
operator ==(other) => other is IsolateGroup && id == other.id;
4592+
4593+
String toString() => '[IsolateGroup ' //
4594+
'type: ${type}, id: ${id}, number: ${number}, name: ${name}, ' //
4595+
'isolates: ${isolates}]';
4596+
}
4597+
44474598
/// See [getInboundReferences].
44484599
class InboundReferences extends Response {
44494600
static InboundReferences parse(Map<String, dynamic> json) =>
@@ -6236,6 +6387,9 @@ class VM extends Response {
62366387
/// A list of isolates running in the VM.
62376388
List<IsolateRef> isolates;
62386389

6390+
/// A list of isolate groups running in the VM.
6391+
List<IsolateGroupRef> isolateGroups;
6392+
62396393
VM({
62406394
@required this.name,
62416395
@required this.architectureBits,
@@ -6246,6 +6400,7 @@ class VM extends Response {
62466400
@required this.pid,
62476401
@required this.startTime,
62486402
@required this.isolates,
6403+
@required this.isolateGroups,
62496404
});
62506405
VM._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
62516406
name = json['name'];
@@ -6258,6 +6413,8 @@ class VM extends Response {
62586413
startTime = json['startTime'];
62596414
isolates = List<IsolateRef>.from(
62606415
createServiceObject(json['isolates'], const ['IsolateRef']));
6416+
isolateGroups = List<IsolateGroupRef>.from(
6417+
createServiceObject(json['isolateGroups'], const ['IsolateGroupRef']));
62616418
}
62626419

62636420
@override
@@ -6274,6 +6431,7 @@ class VM extends Response {
62746431
'pid': pid,
62756432
'startTime': startTime,
62766433
'isolates': isolates.map((f) => f.toJson()).toList(),
6434+
'isolateGroups': isolateGroups.map((f) => f.toJson()).toList(),
62776435
});
62786436
return json;
62796437
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:test/test.dart';
6+
import 'package:vm_service/vm_service.dart';
7+
8+
import 'common/test_helper.dart';
9+
10+
var tests = <VMTest>[
11+
(VmService service) async {
12+
final vm = await service.getVM();
13+
final result =
14+
await service.getIsolateGroupMemoryUsage(vm.isolateGroups.first.id);
15+
expect(result.heapUsage, isPositive);
16+
expect(result.heapCapacity, isPositive);
17+
expect(result.externalUsage, isNonNegative);
18+
},
19+
(VmService service) async {
20+
bool caughtException;
21+
try {
22+
await service.getMemoryUsage('badid');
23+
fail('Unreachable');
24+
} on RPCError catch (e) {
25+
caughtException = true;
26+
expect(
27+
e.details,
28+
contains(
29+
"getMemoryUsage: invalid 'isolateGroupId' parameter: badid"));
30+
}
31+
expect(caughtException, isTrue);
32+
},
33+
];
34+
35+
main(args) async => runVMTests(args, tests);

runtime/observatory/analysis_options.yaml

+5
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,8 @@ analyzer:
1010
- tests/service/get_isolate_after_language_error_test.dart
1111
- tests/service/get_user_level_retaining_path_rpc_test.dart
1212
- tests/service/pause_on_unhandled_async_exceptions_test.dart
13+
14+
linter:
15+
rules:
16+
- prefer_final_fields
17+
- prefer_final_locals

runtime/observatory/lib/models.dart

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ part 'src/models/objects/icdata.dart';
2929
part 'src/models/objects/inbound_references.dart';
3030
part 'src/models/objects/instance.dart';
3131
part 'src/models/objects/isolate.dart';
32+
part 'src/models/objects/isolate_group.dart';
3233
part 'src/models/objects/library.dart';
3334
part 'src/models/objects/local_var_descriptors.dart';
3435
part 'src/models/objects/map_association.dart';
@@ -74,6 +75,7 @@ part 'src/models/repositories/icdata.dart';
7475
part 'src/models/repositories/inbound_references.dart';
7576
part 'src/models/repositories/instance.dart';
7677
part 'src/models/repositories/isolate.dart';
78+
part 'src/models/repositories/isolate_group.dart';
7779
part 'src/models/repositories/library.dart';
7880
part 'src/models/repositories/megamorphiccache.dart';
7981
part 'src/models/repositories/metric.dart';

runtime/observatory/lib/repositories.dart

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ part 'src/repositories/icdata.dart';
3030
part 'src/repositories/inbound_references.dart';
3131
part 'src/repositories/instance.dart';
3232
part 'src/repositories/isolate.dart';
33+
part 'src/repositories/isolate_group.dart';
3334
part 'src/repositories/library.dart';
3435
part 'src/repositories/megamorphiccache.dart';
3536
part 'src/repositories/metric.dart';

0 commit comments

Comments
 (0)