Skip to content

Commit cc00be4

Browse files
authored
Fix CPU Profiler when "advanced developer mode" is enabled (#9528)
1 parent 6722797 commit cc00be4

5 files changed

Lines changed: 162 additions & 5 deletions

File tree

packages/devtools_app/lib/src/screens/profiler/cpu_profile_model.dart

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,13 +1257,22 @@ class _CpuProfileTimelineTree {
12571257
return null;
12581258
}
12591259

1260-
String? get resolvedUrl => isCodeTree && _function is vm_service.FuncRef?
1261-
?
1260+
String? get resolvedUrl {
1261+
if (isCodeTree) {
1262+
if (_function is vm_service.FuncRef?) {
12621263
// TODO(bkonyi): not sure if this is a resolved URL or not, but it's not
12631264
// critical since this is only displayed when advanced developer mode is
12641265
// enabled.
1265-
(_function as vm_service.FuncRef?)?.location?.script?.uri
1266-
: samples.functions?[index].resolvedUrl;
1266+
return (_function as vm_service.FuncRef?)?.location?.script?.uri;
1267+
}
1268+
} else {
1269+
final functions = samples.functions;
1270+
if (functions == null || index >= functions.length) return null;
1271+
return functions[index].resolvedUrl;
1272+
}
1273+
1274+
return null;
1275+
}
12671276

12681277
int? get sourceLine {
12691278
final function = _function;

packages/devtools_app/lib/src/screens/profiler/cpu_profile_service.dart

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
44

5+
import 'package:flutter/foundation.dart';
56
import 'package:vm_service/vm_service.dart';
67

78
import '../../service/vm_flags.dart' as vm_flags;
@@ -28,6 +29,19 @@ extension CpuProfilerExtension on VmService {
2829
final cpuSamples = await serviceConnection.serviceManager.service!
2930
.getCpuSamples(isolateId, startMicros, extentMicros);
3031

32+
return processCpuSamples(
33+
cpuSamples: cpuSamples,
34+
isolateId: isolateId,
35+
advancedDeveloperModeEnabled: advancedDeveloperModeEnabled,
36+
);
37+
}
38+
39+
@visibleForTesting
40+
Future<CpuProfilePair> processCpuSamples({
41+
required CpuSamples cpuSamples,
42+
required String isolateId,
43+
required bool advancedDeveloperModeEnabled,
44+
}) async {
3145
// If advanced developer mode is enabled, getCpuSamples will also include
3246
// code profile details automatically (e.g., code stacks and a list of code
3347
// objects).

packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ TODO: Remove this section if there are not any general updates.
2727

2828
## CPU profiler updates
2929

30-
TODO: Remove this section if there are not any general updates.
30+
- Fixed issue preventing CPU profiles from loading when "advanced developer mode" was enabled. -
31+
[#9528](https://github.com/flutter/devtools/pull/9528)
3132

3233
## Memory updates
3334

packages/devtools_app/test/screens/cpu_profiler/cpu_profile_model_test.dart

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
44

5+
import 'dart:convert';
6+
import 'dart:io';
7+
58
import 'package:devtools_app/src/screens/profiler/cpu_profile_model.dart';
9+
import 'package:devtools_app/src/screens/profiler/cpu_profile_service.dart';
610
import 'package:devtools_app/src/service/service_manager.dart';
11+
import 'package:devtools_app/src/shared/globals.dart';
712
import 'package:devtools_app/src/shared/primitives/utils.dart';
813
import 'package:devtools_app_shared/utils.dart';
914
import 'package:devtools_test/devtools_test.dart';
@@ -40,6 +45,27 @@ void main() {
4045
expect(filtered.profileMetaData.time!.end, 0);
4146
});
4247

48+
// Regression test for https://github.com/flutter/devtools/issues/9526.
49+
test(
50+
'code profile loads in advanced developer mode (regression test)',
51+
() async {
52+
final cpuSamplesFile = File(
53+
'test/test_infra/test_data/cpu_profiler/cpu_samples_with_code_profile.json',
54+
);
55+
final cpuSamplesJson = jsonDecode(cpuSamplesFile.readAsStringSync());
56+
final cpuSamples = CpuSamples.parse(cpuSamplesJson)!;
57+
58+
final profilePair = await serviceConnection.serviceManager.service!
59+
.processCpuSamples(
60+
cpuSamples: cpuSamples,
61+
isolateId: goldenSamplesIsolate,
62+
advancedDeveloperModeEnabled: true,
63+
);
64+
expect(profilePair.codeProfile, isNotNull);
65+
expect(profilePair.functionProfile, isNotNull);
66+
},
67+
);
68+
4369
test('init from parse', () {
4470
expect(
4571
cpuProfileData.stackFramesJson,
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
{
2+
"type": "CpuSamples",
3+
"samplePeriod": 50,
4+
"maxStackDepth": 10,
5+
"sampleCount": 1,
6+
"timeOriginMicros": 0,
7+
"timeExtentMicros": 100,
8+
"pid": 12345,
9+
"functions": [
10+
{
11+
"kind": "Dart",
12+
"inclusiveTicks": 1,
13+
"exclusiveTicks": 0,
14+
"resolvedUrl": "file:///main.dart",
15+
"function": {
16+
"type": "@Function",
17+
"id": "func-0",
18+
"name": "main",
19+
"owner": { "type": "@Library", "id": "lib-0", "name": "", "uri": "file:///main.dart" },
20+
"isStatic": true,
21+
"isConst": false,
22+
"implicit": false
23+
}
24+
},
25+
{
26+
"kind": "Dart",
27+
"inclusiveTicks": 1,
28+
"exclusiveTicks": 1,
29+
"resolvedUrl": "file:///main.dart",
30+
"function": {
31+
"type": "@Function",
32+
"id": "func-1",
33+
"name": "helperFunction",
34+
"owner": { "type": "@Library", "id": "lib-0", "name": "", "uri": "file:///main.dart" },
35+
"isStatic": true,
36+
"isConst": false,
37+
"implicit": false
38+
}
39+
}
40+
],
41+
"_codes": [
42+
{
43+
"kind": "Dart",
44+
"inclusiveTicks": 1,
45+
"exclusiveTicks": 0,
46+
"code": {
47+
"type": "@Code",
48+
"kind": "Dart",
49+
"name": "main",
50+
"id": "code-0",
51+
"function": {
52+
"type": "@Function",
53+
"id": "func-0",
54+
"name": "main",
55+
"owner": { "type": "@Library", "id": "lib-0", "name": "", "uri": "file:///main.dart" },
56+
"isStatic": true,
57+
"isConst": false,
58+
"implicit": false
59+
}
60+
}
61+
},
62+
{
63+
"kind": "Dart",
64+
"inclusiveTicks": 1,
65+
"exclusiveTicks": 1,
66+
"code": {
67+
"type": "@Code",
68+
"kind": "Dart",
69+
"name": "helperFunction",
70+
"id": "code-1",
71+
"function": {
72+
"type": "@Function",
73+
"id": "func-1",
74+
"name": "helperFunction",
75+
"owner": { "type": "@Library", "id": "lib-0", "name": "", "uri": "file:///main.dart" },
76+
"isStatic": true,
77+
"isConst": false,
78+
"implicit": false
79+
}
80+
}
81+
},
82+
{
83+
"kind": "Stub",
84+
"inclusiveTicks": 1,
85+
"exclusiveTicks": 0,
86+
"code": {
87+
"type": "@Code",
88+
"kind": "Stub",
89+
"name": "WriteBarrierStub",
90+
"id": "code-2",
91+
"function": {
92+
"type": "NativeFunction",
93+
"id": "native-2",
94+
"name": "WriteBarrierStub"
95+
}
96+
}
97+
}
98+
],
99+
"samples": [
100+
{
101+
"tid": 100,
102+
"timestamp": 50,
103+
"stack": [0, 1],
104+
"_codeStack": [2]
105+
}
106+
]
107+
}

0 commit comments

Comments
 (0)