Skip to content

Commit 48a8574

Browse files
author
Brian Vaughn
authored
Fixed edge case bug in Profiler (#24031)
1 parent 72a933d commit 48a8574

File tree

3 files changed

+220
-29
lines changed

3 files changed

+220
-29
lines changed

packages/react-devtools-shared/src/__tests__/__snapshots__/profilingCache-test.js.snap

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2960,6 +2960,94 @@ Object {
29602960
}
29612961
`;
29622962

2963+
exports[`ProfilingCache should collect data for each root (including ones added or mounted after profiling started): Data for root Parent 3`] = `
2964+
Object {
2965+
"commitData": Array [
2966+
Object {
2967+
"changeDescriptions": Map {},
2968+
"duration": 0,
2969+
"effectDuration": 0,
2970+
"fiberActualDurations": Map {},
2971+
"fiberSelfDurations": Map {},
2972+
"passiveEffectDuration": 0,
2973+
"priorityLevel": "Immediate",
2974+
"timestamp": 34,
2975+
"updaters": Array [
2976+
Object {
2977+
"displayName": "render()",
2978+
"hocDisplayNames": null,
2979+
"id": 7,
2980+
"key": null,
2981+
"type": 11,
2982+
},
2983+
],
2984+
},
2985+
],
2986+
"displayName": "Parent",
2987+
"initialTreeBaseDurations": Map {
2988+
7 => 11,
2989+
8 => 11,
2990+
10 => 0,
2991+
11 => 1,
2992+
},
2993+
"operations": Array [
2994+
Array [
2995+
1,
2996+
7,
2997+
0,
2998+
2,
2999+
4,
3000+
11,
3001+
10,
3002+
8,
3003+
7,
3004+
],
3005+
],
3006+
"rootID": 7,
3007+
"snapshots": Map {
3008+
7 => Object {
3009+
"children": Array [
3010+
8,
3011+
],
3012+
"displayName": null,
3013+
"hocDisplayNames": null,
3014+
"id": 7,
3015+
"key": null,
3016+
"type": 11,
3017+
},
3018+
8 => Object {
3019+
"children": Array [
3020+
10,
3021+
11,
3022+
],
3023+
"displayName": "Parent",
3024+
"hocDisplayNames": null,
3025+
"id": 8,
3026+
"key": null,
3027+
"type": 5,
3028+
},
3029+
10 => Object {
3030+
"children": Array [],
3031+
"displayName": "Child",
3032+
"hocDisplayNames": null,
3033+
"id": 10,
3034+
"key": "0",
3035+
"type": 5,
3036+
},
3037+
11 => Object {
3038+
"children": Array [],
3039+
"displayName": "Child",
3040+
"hocDisplayNames": Array [
3041+
"Memo",
3042+
],
3043+
"id": 11,
3044+
"key": null,
3045+
"type": 8,
3046+
},
3047+
},
3048+
}
3049+
`;
3050+
29633051
exports[`ProfilingCache should collect data for each root (including ones added or mounted after profiling started): imported data 1`] = `
29643052
Object {
29653053
"dataForRoots": Array [
@@ -3504,6 +3592,115 @@ Object {
35043592
"rootID": 13,
35053593
"snapshots": Array [],
35063594
},
3595+
Object {
3596+
"commitData": Array [
3597+
Object {
3598+
"changeDescriptions": Array [],
3599+
"duration": 0,
3600+
"effectDuration": 0,
3601+
"fiberActualDurations": Array [],
3602+
"fiberSelfDurations": Array [],
3603+
"passiveEffectDuration": 0,
3604+
"priorityLevel": "Immediate",
3605+
"timestamp": 34,
3606+
"updaters": Array [
3607+
Object {
3608+
"displayName": "render()",
3609+
"hocDisplayNames": null,
3610+
"id": 7,
3611+
"key": null,
3612+
"type": 11,
3613+
},
3614+
],
3615+
},
3616+
],
3617+
"displayName": "Parent",
3618+
"initialTreeBaseDurations": Array [
3619+
Array [
3620+
7,
3621+
11,
3622+
],
3623+
Array [
3624+
8,
3625+
11,
3626+
],
3627+
Array [
3628+
10,
3629+
0,
3630+
],
3631+
Array [
3632+
11,
3633+
1,
3634+
],
3635+
],
3636+
"operations": Array [
3637+
Array [
3638+
1,
3639+
7,
3640+
0,
3641+
2,
3642+
4,
3643+
11,
3644+
10,
3645+
8,
3646+
7,
3647+
],
3648+
],
3649+
"rootID": 7,
3650+
"snapshots": Array [
3651+
Array [
3652+
7,
3653+
Object {
3654+
"children": Array [
3655+
8,
3656+
],
3657+
"displayName": null,
3658+
"hocDisplayNames": null,
3659+
"id": 7,
3660+
"key": null,
3661+
"type": 11,
3662+
},
3663+
],
3664+
Array [
3665+
8,
3666+
Object {
3667+
"children": Array [
3668+
10,
3669+
11,
3670+
],
3671+
"displayName": "Parent",
3672+
"hocDisplayNames": null,
3673+
"id": 8,
3674+
"key": null,
3675+
"type": 5,
3676+
},
3677+
],
3678+
Array [
3679+
10,
3680+
Object {
3681+
"children": Array [],
3682+
"displayName": "Child",
3683+
"hocDisplayNames": null,
3684+
"id": 10,
3685+
"key": "0",
3686+
"type": 5,
3687+
},
3688+
],
3689+
Array [
3690+
11,
3691+
Object {
3692+
"children": Array [],
3693+
"displayName": "Child",
3694+
"hocDisplayNames": Array [
3695+
"Memo",
3696+
],
3697+
"id": 11,
3698+
"key": null,
3699+
"type": 8,
3700+
},
3701+
],
3702+
],
3703+
},
35073704
],
35083705
"timelineData": Array [
35093706
Object {

packages/react-devtools-shared/src/__tests__/profilingCache-test.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,7 @@ describe('ProfilingCache', () => {
110110
});
111111
}
112112

113-
// No profiling data gets logged for the 2nd root (container B)
114-
// because it doesn't render anything while profiling.
115-
// (Technically it unmounts but we don't profile root unmounts.)
116-
expect(allProfilingDataForRoots).toHaveLength(2);
113+
expect(allProfilingDataForRoots).toHaveLength(3);
117114

118115
utils.exportImportHelper(bridge, store);
119116

packages/react-devtools-shared/src/backend/renderer.js

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1624,20 +1624,29 @@ export function attach(
16241624
pendingOperations.push(op);
16251625
}
16261626

1627-
function flushOrQueueOperations(operations: OperationsArray): void {
1628-
if (operations.length === 3) {
1629-
// This operations array is a no op: [renderer ID, root ID, string table size (0)]
1630-
// We can usually skip sending updates like this across the bridge, unless we're Profiling.
1631-
// In that case, even though the tree didn't change– some Fibers may have still rendered.
1627+
function shouldBailoutWithPendingOperations() {
1628+
if (isProfiling) {
16321629
if (
1633-
!isProfiling ||
1634-
currentCommitProfilingMetadata == null ||
1635-
currentCommitProfilingMetadata.durations.length === 0
1630+
currentCommitProfilingMetadata != null &&
1631+
currentCommitProfilingMetadata.durations.length > 0
16361632
) {
1637-
return;
1633+
return false;
16381634
}
16391635
}
16401636

1637+
return (
1638+
pendingOperations.length === 0 &&
1639+
pendingRealUnmountedIDs.length === 0 &&
1640+
pendingSimulatedUnmountedIDs.length === 0 &&
1641+
pendingUnmountedRootID === null
1642+
);
1643+
}
1644+
1645+
function flushOrQueueOperations(operations: OperationsArray): void {
1646+
if (shouldBailoutWithPendingOperations()) {
1647+
return;
1648+
}
1649+
16411650
if (pendingOperationsQueue !== null) {
16421651
pendingOperationsQueue.push(operations);
16431652
} else {
@@ -1668,7 +1677,7 @@ export function attach(
16681677

16691678
recordPendingErrorsAndWarnings();
16701679

1671-
if (pendingOperations.length === 0) {
1680+
if (shouldBailoutWithPendingOperations()) {
16721681
// No warnings or errors to flush; we can bail out early here too.
16731682
return;
16741683
}
@@ -1791,12 +1800,7 @@ export function attach(
17911800
// We do this just before flushing, so we can ignore errors for no-longer-mounted Fibers.
17921801
recordPendingErrorsAndWarnings();
17931802

1794-
if (
1795-
pendingOperations.length === 0 &&
1796-
pendingRealUnmountedIDs.length === 0 &&
1797-
pendingSimulatedUnmountedIDs.length === 0 &&
1798-
pendingUnmountedRootID === null
1799-
) {
1803+
if (shouldBailoutWithPendingOperations()) {
18001804
// If we aren't profiling, we can just bail out here.
18011805
// No use sending an empty update over the bridge.
18021806
//
@@ -1805,9 +1809,7 @@ export function attach(
18051809
// (2) the operations array for each commit
18061810
// Because of this, it's important that the operations and metadata arrays align,
18071811
// So it's important not to omit even empty operations while profiling is active.
1808-
if (!isProfiling) {
1809-
return;
1810-
}
1812+
return;
18111813
}
18121814

18131815
const numUnmountIDs =
@@ -2724,12 +2726,7 @@ export function attach(
27242726
}
27252727

27262728
if (isProfiling && isProfilingSupported) {
2727-
// Make sure at least one Fiber performed work during this commit.
2728-
// If not, don't send it to the frontend; showing an empty commit in the Profiler is confusing.
2729-
if (
2730-
currentCommitProfilingMetadata != null &&
2731-
currentCommitProfilingMetadata.durations.length > 0
2732-
) {
2729+
if (!shouldBailoutWithPendingOperations()) {
27332730
const commitProfilingMetadata = ((rootToCommitProfilingMetadataMap: any): CommitProfilingMetadataMap).get(
27342731
currentRootID,
27352732
);

0 commit comments

Comments
 (0)