3e83400e0f
This change adds two new RPCs and various new properties: - getAllocationTraces - setTraceClassAllocation - classId and identityHashCode properties in CpuSample - traceAllocations property in Class TEST=get_allocation_traces_test.dart package:vm_service has been regenerated for 3.43 of the service protocol and is ready for a 6.1.0 release. Change-Id: Ia8ed055423798d7d17fe9f5fd74efb4239b875fc Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/182666 Commit-Queue: Ben Konyi <bkonyi@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
132 lines
3.8 KiB
Dart
132 lines
3.8 KiB
Dart
// Copyright (c) 2021, 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:developer';
|
|
import 'package:observatory/models.dart' as M;
|
|
import 'package:observatory/service_io.dart';
|
|
import 'package:observatory/sample_profile.dart';
|
|
import 'package:test/test.dart';
|
|
import 'service_test_common.dart';
|
|
import 'test_helper.dart';
|
|
|
|
class Foo {
|
|
Foo() {
|
|
print('Foo');
|
|
}
|
|
}
|
|
|
|
class Bar {
|
|
Bar() {
|
|
print('Bar');
|
|
}
|
|
}
|
|
|
|
void test() {
|
|
debugger();
|
|
// Toggled on for Foo.
|
|
debugger();
|
|
debugger();
|
|
// Traced allocation.
|
|
Foo();
|
|
// Untraced allocation.
|
|
Bar();
|
|
// Toggled on for Bar.
|
|
debugger();
|
|
debugger();
|
|
// Traced allocation.
|
|
Bar();
|
|
debugger();
|
|
}
|
|
|
|
var tests = <IsolateTest>[
|
|
hasStoppedAtBreakpoint,
|
|
|
|
// Initial.
|
|
(Isolate isolate) async {
|
|
// Verify initial state of 'Foo'.
|
|
final fooClass = (await getClassFromRootLib(isolate, 'Foo'))!;
|
|
expect(fooClass.name, equals('Foo'));
|
|
print(fooClass.id);
|
|
expect(fooClass.traceAllocations, isFalse);
|
|
await fooClass.setTraceAllocations(true);
|
|
await fooClass.reload();
|
|
expect(fooClass.traceAllocations, true);
|
|
},
|
|
|
|
resumeIsolate,
|
|
hasStoppedAtBreakpoint,
|
|
// Extra debugger stop, continue to allow the allocation stubs to be switched
|
|
// over. This is a bug but low priority.
|
|
resumeIsolate,
|
|
hasStoppedAtBreakpoint,
|
|
|
|
// Allocation profile.
|
|
(Isolate isolate) async {
|
|
final fooClass = (await getClassFromRootLib(isolate, 'Foo'))!;
|
|
await fooClass.reload();
|
|
expect(fooClass.traceAllocations, true);
|
|
|
|
final profileResponse = (await isolate.getAllocationTraces()) as ServiceMap;
|
|
expect(profileResponse, isNotNull);
|
|
expect(profileResponse['type'], 'CpuSamples');
|
|
expect(profileResponse['samples'].length, 1);
|
|
expect(profileResponse['samples'][0]['identityHashCode'], isNotNull);
|
|
expect(profileResponse['samples'][0]['identityHashCode'] != 0, true);
|
|
await fooClass.setTraceAllocations(false);
|
|
await fooClass.reload();
|
|
expect(fooClass.traceAllocations, isFalse);
|
|
|
|
// Verify the allocation trace for the `Foo()` allocation.
|
|
final cpuProfile = SampleProfile();
|
|
await cpuProfile.load(isolate, profileResponse);
|
|
cpuProfile.buildCodeCallerAndCallees();
|
|
cpuProfile.buildFunctionCallerAndCallees();
|
|
final tree = cpuProfile.loadCodeTree(M.ProfileTreeDirection.exclusive);
|
|
dynamic node = tree.root;
|
|
final expected = [
|
|
'Root',
|
|
'[Unoptimized] test',
|
|
'[Unoptimized] test',
|
|
'[Unoptimized] _Closure.call',
|
|
'[Unoptimized] _ServiceTesteeRunner.run',
|
|
];
|
|
for (var i = 0; i < expected.length; i++) {
|
|
expect(node.profileCode.code.name, equals(expected[i]));
|
|
// Depth first traversal.
|
|
if (node.children.length == 0) {
|
|
node = null;
|
|
} else {
|
|
node = node.children[0];
|
|
}
|
|
expect(node, isNotNull);
|
|
}
|
|
},
|
|
resumeIsolate,
|
|
hasStoppedAtBreakpoint,
|
|
(Isolate isolate) async {
|
|
// Trace Bar.
|
|
final barClass = (await getClassFromRootLib(isolate, 'Bar'))!;
|
|
await barClass.reload();
|
|
expect(barClass.traceAllocations, false);
|
|
await barClass.setTraceAllocations(true);
|
|
await barClass.reload();
|
|
expect(barClass.traceAllocations, true);
|
|
},
|
|
|
|
resumeIsolate,
|
|
hasStoppedAtBreakpoint,
|
|
// Extra debugger stop, continue to allow the allocation stubs to be switched
|
|
// over. This is a bug but low priority.
|
|
resumeIsolate,
|
|
hasStoppedAtBreakpoint,
|
|
|
|
(Isolate isolate) async {
|
|
// Ensure the allocation of `Bar()` was recorded.
|
|
final profileResponse = (await isolate.getAllocationTraces()) as ServiceMap;
|
|
expect(profileResponse['samples'].length, 2);
|
|
},
|
|
];
|
|
|
|
main(args) async => runIsolateTests(args, tests, testeeConcurrent: test);
|