@samitouri / QOS-React-2 / commits / bf11788bf0

DevTools Profiler: Add commit and post-commit durations to UI (#20984)

Brian Vaughn committed Mar 17, 2021 at 12:27 UTC bf11788bf0c2e861dc6378ac9ab59d37e7c3e812
14 files changed +403 -43
packages/react-devtools-shared/src/__tests__/__snapshots__/profilingCache-test.js.snap
+94
@@ -26,6 +26,7 @@ Object {
26 },
27 },
28 "duration": 16,
29 + "effectDuration": null,
30 "fiberActualDurations": Map {
31 1 => 16,
32 2 => 16,
@@ -39,6 +40,7 @@ Object {
40 5 => 1,
41 },
42 "interactionIDs": Array [],
43 + "passiveEffectDuration": null,
44 "priorityLevel": "Normal",
45 "timestamp": 16,
46 }
@@ -63,6 +65,7 @@ Object {
65 },
66 },
67 "duration": 15,
68 + "effectDuration": null,
69 "fiberActualDurations": Map {
70 1 => 15,
71 2 => 15,
@@ -76,6 +79,7 @@ Object {
79 4 => 2,
80 },
81 "interactionIDs": Array [],
82 + "passiveEffectDuration": null,
83 "priorityLevel": "Normal",
84 "timestamp": 15,
85 }
@@ -93,6 +97,7 @@ Object {
97 },
98 },
99 "duration": 3,
100 + "effectDuration": null,
101 "fiberActualDurations": Map {
102 5 => 3,
103 3 => 3,
@@ -102,6 +107,7 @@ Object {
107 3 => 0,
108 },
109 "interactionIDs": Array [],
110 + "passiveEffectDuration": null,
111 "priorityLevel": "Immediate",
112 "timestamp": 18,
113 }
@@ -140,6 +146,7 @@ Object {
146 },
147 },
148 "duration": 12,
149 + "effectDuration": null,
150 "fiberActualDurations": Map {
151 1 => 12,
152 2 => 12,
@@ -155,6 +162,7 @@ Object {
162 5 => 1,
163 },
164 "interactionIDs": Array [],
165 + "passiveEffectDuration": null,
166 "priorityLevel": "Normal",
167 "timestamp": 12,
168 }
@@ -195,6 +203,7 @@ Object {
203 },
204 },
205 "duration": 13,
206 + "effectDuration": null,
207 "fiberActualDurations": Map {
208 3 => 0,
209 4 => 1,
@@ -210,6 +219,7 @@ Object {
219 1 => 0,
220 },
221 "interactionIDs": Array [],
222 + "passiveEffectDuration": null,
223 "priorityLevel": "Immediate",
224 "timestamp": 25,
225 }
@@ -236,6 +246,7 @@ Object {
246 },
247 },
248 "duration": 10,
249 + "effectDuration": null,
250 "fiberActualDurations": Map {
251 3 => 0,
252 2 => 10,
@@ -247,6 +258,7 @@ Object {
258 1 => 0,
259 },
260 "interactionIDs": Array [],
261 + "passiveEffectDuration": null,
262 "priorityLevel": "Immediate",
263 "timestamp": 35,
264 }
@@ -266,6 +278,7 @@ Object {
278 },
279 },
280 "duration": 10,
281 + "effectDuration": null,
282 "fiberActualDurations": Map {
283 2 => 10,
284 1 => 10,
@@ -275,6 +288,7 @@ Object {
288 1 => 0,
289 },
290 "interactionIDs": Array [],
291 + "passiveEffectDuration": null,
292 "priorityLevel": "Immediate",
293 "timestamp": 45,
294 }
@@ -329,6 +343,7 @@ Object {
343 ],
344 ],
345 "duration": 12,
346 + "effectDuration": null,
347 "fiberActualDurations": Array [
348 Array [
349 1,
@@ -374,6 +389,7 @@ Object {
389 ],
390 ],
391 "interactionIDs": Array [],
392 + "passiveEffectDuration": null,
393 "priorityLevel": "Normal",
394 "timestamp": 12,
395 },
@@ -423,6 +439,7 @@ Object {
439 ],
440 ],
441 "duration": 13,
442 + "effectDuration": null,
443 "fiberActualDurations": Array [
444 Array [
445 3,
@@ -468,6 +485,7 @@ Object {
485 ],
486 ],
487 "interactionIDs": Array [],
488 + "passiveEffectDuration": null,
489 "priorityLevel": "Immediate",
490 "timestamp": 25,
491 },
@@ -497,6 +515,7 @@ Object {
515 ],
516 ],
517 "duration": 10,
518 + "effectDuration": null,
519 "fiberActualDurations": Array [
520 Array [
521 3,
@@ -526,6 +545,7 @@ Object {
545 ],
546 ],
547 "interactionIDs": Array [],
548 + "passiveEffectDuration": null,
549 "priorityLevel": "Immediate",
550 "timestamp": 35,
551 },
@@ -545,6 +565,7 @@ Object {
565 ],
566 ],
567 "duration": 10,
568 + "effectDuration": null,
569 "fiberActualDurations": Array [
570 Array [
571 2,
@@ -566,6 +587,7 @@ Object {
587 ],
588 ],
589 "interactionIDs": Array [],
590 + "passiveEffectDuration": null,
591 "priorityLevel": "Immediate",
592 "timestamp": 45,
593 },
@@ -792,6 +814,7 @@ Object {
814 ],
815 ],
816 "duration": 11,
817 + "effectDuration": null,
818 "fiberActualDurations": Array [
819 Array [
820 1,
@@ -829,6 +852,7 @@ Object {
852 ],
853 ],
854 "interactionIDs": Array [],
855 + "passiveEffectDuration": null,
856 "priorityLevel": "Normal",
857 "timestamp": 11,
858 },
@@ -868,6 +892,7 @@ Object {
892 ],
893 ],
894 "duration": 11,
895 + "effectDuration": null,
896 "fiberActualDurations": Array [
897 Array [
898 3,
@@ -905,6 +930,7 @@ Object {
930 ],
931 ],
932 "interactionIDs": Array [],
933 + "passiveEffectDuration": null,
934 "priorityLevel": "Immediate",
935 "timestamp": 22,
936 },
@@ -954,6 +980,7 @@ Object {
980 ],
981 ],
982 "duration": 13,
983 + "effectDuration": null,
984 "fiberActualDurations": Array [
985 Array [
986 3,
@@ -999,6 +1026,7 @@ Object {
1026 ],
1027 ],
1028 "interactionIDs": Array [],
1029 + "passiveEffectDuration": null,
1030 "priorityLevel": "Immediate",
1031 "timestamp": 35,
1032 },
@@ -1183,6 +1211,7 @@ Object {
1211 },
1212 },
1213 "duration": 13,
1214 + "effectDuration": null,
1215 "fiberActualDurations": Map {
1216 3 => 0,
1217 4 => 1,
@@ -1198,6 +1227,7 @@ Object {
1227 1 => 0,
1228 },
1229 "interactionIDs": Array [],
1230 + "passiveEffectDuration": null,
1231 "priorityLevel": "Immediate",
1232 "timestamp": 13,
1233 },
@@ -1221,6 +1251,7 @@ Object {
1251 },
1252 },
1253 "duration": 10,
1254 + "effectDuration": null,
1255 "fiberActualDurations": Map {
1256 3 => 0,
1257 2 => 10,
@@ -1232,6 +1263,7 @@ Object {
1263 1 => 0,
1264 },
1265 "interactionIDs": Array [],
1266 + "passiveEffectDuration": null,
1267 "priorityLevel": "Immediate",
1268 "timestamp": 34,
1269 },
@@ -1248,6 +1280,7 @@ Object {
1280 },
1281 },
1282 "duration": 10,
1283 + "effectDuration": null,
1284 "fiberActualDurations": Map {
1285 2 => 10,
1286 1 => 10,
@@ -1257,6 +1290,7 @@ Object {
1290 1 => 0,
1291 },
1292 "interactionIDs": Array [],
1293 + "passiveEffectDuration": null,
1294 "priorityLevel": "Immediate",
1295 "timestamp": 44,
1296 },
@@ -1419,6 +1453,7 @@ Object {
1453 },
1454 },
1455 "duration": 11,
1456 + "effectDuration": null,
1457 "fiberActualDurations": Map {
1458 11 => 11,
1459 12 => 11,
@@ -1432,6 +1467,7 @@ Object {
1467 14 => 1,
1468 },
1469 "interactionIDs": Array [],
1470 + "passiveEffectDuration": null,
1471 "priorityLevel": "Normal",
1472 "timestamp": 24,
1473 },
@@ -1511,9 +1547,11 @@ Object {
1547 Object {
1548 "changeDescriptions": Map {},
1549 "duration": 0,
1550 + "effectDuration": null,
1551 "fiberActualDurations": Map {},
1552 "fiberSelfDurations": Map {},
1553 "interactionIDs": Array [],
1554 + "passiveEffectDuration": null,
1555 "priorityLevel": "Normal",
1556 "timestamp": 34,
1557 },
@@ -1636,6 +1674,7 @@ Object {
1674 ],
1675 ],
1676 "duration": 13,
1677 + "effectDuration": null,
1678 "fiberActualDurations": Array [
1679 Array [
1680 3,
@@ -1681,6 +1720,7 @@ Object {
1720 ],
1721 ],
1722 "interactionIDs": Array [],
1723 + "passiveEffectDuration": null,
1724 "priorityLevel": "Immediate",
1725 "timestamp": 13,
1726 },
@@ -1710,6 +1750,7 @@ Object {
1750 ],
1751 ],
1752 "duration": 10,
1753 + "effectDuration": null,
1754 "fiberActualDurations": Array [
1755 Array [
1756 3,
@@ -1739,6 +1780,7 @@ Object {
1780 ],
1781 ],
1782 "interactionIDs": Array [],
1783 + "passiveEffectDuration": null,
1784 "priorityLevel": "Immediate",
1785 "timestamp": 34,
1786 },
@@ -1758,6 +1800,7 @@ Object {
1800 ],
1801 ],
1802 "duration": 10,
1803 + "effectDuration": null,
1804 "fiberActualDurations": Array [
1805 Array [
1806 2,
@@ -1779,6 +1822,7 @@ Object {
1822 ],
1823 ],
1824 "interactionIDs": Array [],
1825 + "passiveEffectDuration": null,
1826 "priorityLevel": "Immediate",
1827 "timestamp": 44,
1828 },
@@ -1977,6 +2021,7 @@ Object {
2021 ],
2022 ],
2023 "duration": 11,
2024 + "effectDuration": null,
2025 "fiberActualDurations": Array [
2026 Array [
2027 11,
@@ -2014,6 +2059,7 @@ Object {
2059 ],
2060 ],
2061 "interactionIDs": Array [],
2062 + "passiveEffectDuration": null,
2063 "priorityLevel": "Normal",
2064 "timestamp": 24,
2065 },
@@ -2090,9 +2136,11 @@ Object {
2136 Object {
2137 "changeDescriptions": Array [],
2138 "duration": 0,
2139 + "effectDuration": null,
2140 "fiberActualDurations": Array [],
2141 "fiberSelfDurations": Array [],
2142 "interactionIDs": Array [],
2143 + "passiveEffectDuration": null,
2144 "priorityLevel": "Normal",
2145 "timestamp": 34,
2146 },
@@ -2197,6 +2245,7 @@ Object {
2245 Object {
2246 "changeDescriptions": Map {},
2247 "duration": 0,
2248 + "effectDuration": null,
2249 "fiberActualDurations": Map {
2250 1 => 0,
2251 2 => 0,
@@ -2206,6 +2255,7 @@ Object {
2255 2 => 0,
2256 },
2257 "interactionIDs": Array [],
2258 + "passiveEffectDuration": null,
2259 "priorityLevel": "Normal",
2260 "timestamp": 0,
2261 },
@@ -2262,6 +2312,7 @@ Object {
2312 },
2313 },
2314 "duration": 0,
2315 + "effectDuration": null,
2316 "fiberActualDurations": Map {
2317 1 => 0,
2318 2 => 0,
@@ -2273,6 +2324,7 @@ Object {
2324 3 => 0,
2325 },
2326 "interactionIDs": Array [],
2327 + "passiveEffectDuration": null,
2328 "priorityLevel": "Normal",
2329 "timestamp": 0,
2330 }
@@ -2292,6 +2344,7 @@ Object {
2344 },
2345 },
2346 "duration": 0,
2347 + "effectDuration": null,
2348 "fiberActualDurations": Map {
2349 3 => 0,
2350 2 => 0,
@@ -2303,6 +2356,7 @@ Object {
2356 1 => 0,
2357 },
2358 "interactionIDs": Array [],
2359 + "passiveEffectDuration": null,
2360 "priorityLevel": "Immediate",
2361 "timestamp": 0,
2362 }
@@ -2320,6 +2374,7 @@ Object {
2374 },
2375 },
2376 "duration": 0,
2377 + "effectDuration": null,
2378 "fiberActualDurations": Map {
2379 3 => 0,
2380 },
@@ -2327,6 +2382,7 @@ Object {
2382 3 => 0,
2383 },
2384 "interactionIDs": Array [],
2385 + "passiveEffectDuration": null,
2386 "priorityLevel": "Immediate",
2387 "timestamp": 0,
2388 }
@@ -2344,6 +2400,7 @@ Object {
2400 },
2401 },
2402 "duration": 0,
2403 + "effectDuration": null,
2404 "fiberActualDurations": Map {
2405 3 => 0,
2406 },
@@ -2351,6 +2408,7 @@ Object {
2408 3 => 0,
2409 },
2410 "interactionIDs": Array [],
2411 + "passiveEffectDuration": null,
2412 "priorityLevel": "Immediate",
2413 "timestamp": 0,
2414 }
@@ -2368,6 +2426,7 @@ Object {
2426 },
2427 },
2428 "duration": 0,
2429 + "effectDuration": null,
2430 "fiberActualDurations": Map {
2431 3 => 0,
2432 2 => 0,
@@ -2379,6 +2438,7 @@ Object {
2438 1 => 0,
2439 },
2440 "interactionIDs": Array [],
2441 + "passiveEffectDuration": null,
2442 "priorityLevel": "Immediate",
2443 "timestamp": 0,
2444 }
@@ -2403,6 +2463,7 @@ Object {
2463 ],
2464 ],
2465 "duration": 0,
2466 + "effectDuration": null,
2467 "fiberActualDurations": Array [
2468 Array [
2469 1,
@@ -2432,6 +2493,7 @@ Object {
2493 ],
2494 ],
2495 "interactionIDs": Array [],
2496 + "passiveEffectDuration": null,
2497 "priorityLevel": "Normal",
2498 "timestamp": 0,
2499 },
@@ -2451,6 +2513,7 @@ Object {
2513 ],
2514 ],
2515 "duration": 0,
2516 + "effectDuration": null,
2517 "fiberActualDurations": Array [
2518 Array [
2519 3,
@@ -2480,6 +2543,7 @@ Object {
2543 ],
2544 ],
2545 "interactionIDs": Array [],
2546 + "passiveEffectDuration": null,
2547 "priorityLevel": "Immediate",
2548 "timestamp": 0,
2549 },
@@ -2497,6 +2561,7 @@ Object {
2561 ],
2562 ],
2563 "duration": 0,
2564 + "effectDuration": null,
2565 "fiberActualDurations": Array [
2566 Array [
2567 3,
@@ -2510,6 +2575,7 @@ Object {
2575 ],
2576 ],
2577 "interactionIDs": Array [],
2578 + "passiveEffectDuration": null,
2579 "priorityLevel": "Immediate",
2580 "timestamp": 0,
2581 },
@@ -2527,6 +2593,7 @@ Object {
2593 ],
2594 ],
2595 "duration": 0,
2596 + "effectDuration": null,
2597 "fiberActualDurations": Array [
2598 Array [
2599 3,
@@ -2540,6 +2607,7 @@ Object {
2607 ],
2608 ],
2609 "interactionIDs": Array [],
2610 + "passiveEffectDuration": null,
2611 "priorityLevel": "Immediate",
2612 "timestamp": 0,
2613 },
@@ -2557,6 +2625,7 @@ Object {
2625 ],
2626 ],
2627 "duration": 0,
2628 + "effectDuration": null,
2629 "fiberActualDurations": Array [
2630 Array [
2631 3,
@@ -2586,6 +2655,7 @@ Object {
2655 ],
2656 ],
2657 "interactionIDs": Array [],
2658 + "passiveEffectDuration": null,
2659 "priorityLevel": "Immediate",
2660 "timestamp": 0,
2661 },
@@ -2721,6 +2791,7 @@ Object {
2791 },
2792 },
2793 "duration": 0,
2794 + "effectDuration": null,
2795 "fiberActualDurations": Map {
2796 1 => 0,
2797 2 => 0,
@@ -2740,6 +2811,7 @@ Object {
2811 7 => 0,
2812 },
2813 "interactionIDs": Array [],
2814 + "passiveEffectDuration": null,
2815 "priorityLevel": "Normal",
2816 "timestamp": 0,
2817 }
@@ -2793,6 +2865,7 @@ Object {
2865 },
2866 },
2867 "duration": 0,
2868 + "effectDuration": null,
2869 "fiberActualDurations": Map {
2870 5 => 0,
2871 4 => 0,
@@ -2810,6 +2883,7 @@ Object {
2883 2 => 0,
2884 },
2885 "interactionIDs": Array [],
2886 + "passiveEffectDuration": null,
2887 "priorityLevel": "Immediate",
2888 "timestamp": 0,
2889 }
@@ -2857,6 +2931,7 @@ Object {
2931 },
2932 },
2933 "duration": 0,
2934 + "effectDuration": null,
2935 "fiberActualDurations": Map {
2936 5 => 0,
2937 4 => 0,
@@ -2876,6 +2951,7 @@ Object {
2951 1 => 0,
2952 },
2953 "interactionIDs": Array [],
2954 + "passiveEffectDuration": null,
2955 "priorityLevel": "Immediate",
2956 "timestamp": 0,
2957 }
@@ -2924,6 +3000,7 @@ Object {
3000 },
3001 },
3002 "duration": 0,
3003 + "effectDuration": null,
3004 "fiberActualDurations": Map {
3005 5 => 0,
3006 4 => 0,
@@ -2943,6 +3020,7 @@ Object {
3020 1 => 0,
3021 },
3022 "interactionIDs": Array [],
3023 + "passiveEffectDuration": null,
3024 "priorityLevel": "Immediate",
3025 "timestamp": 0,
3026 }
@@ -2990,6 +3068,7 @@ Object {
3068 },
3069 },
3070 "duration": 0,
3071 + "effectDuration": null,
3072 "fiberActualDurations": Map {
3073 5 => 0,
3074 4 => 0,
@@ -3009,6 +3088,7 @@ Object {
3088 1 => 0,
3089 },
3090 "interactionIDs": Array [],
3091 + "passiveEffectDuration": null,
3092 "priorityLevel": "Immediate",
3093 "timestamp": 0,
3094 }
@@ -3073,6 +3153,7 @@ Object {
3153 ],
3154 ],
3155 "duration": 0,
3156 + "effectDuration": null,
3157 "fiberActualDurations": Array [
3158 Array [
3159 1,
@@ -3134,6 +3215,7 @@ Object {
3215 ],
3216 ],
3217 "interactionIDs": Array [],
3218 + "passiveEffectDuration": null,
3219 "priorityLevel": "Normal",
3220 "timestamp": 0,
3221 },
@@ -3199,6 +3281,7 @@ Object {
3281 ],
3282 ],
3283 "duration": 0,
3284 + "effectDuration": null,
3285 "fiberActualDurations": Array [
3286 Array [
3287 5,
@@ -3252,6 +3335,7 @@ Object {
3335 ],
3336 ],
3337 "interactionIDs": Array [],
3338 + "passiveEffectDuration": null,
3339 "priorityLevel": "Immediate",
3340 "timestamp": 0,
3341 },
@@ -3311,6 +3395,7 @@ Object {
3395 ],
3396 ],
3397 "duration": 0,
3398 + "effectDuration": null,
3399 "fiberActualDurations": Array [
3400 Array [
3401 5,
@@ -3372,6 +3457,7 @@ Object {
3457 ],
3458 ],
3459 "interactionIDs": Array [],
3460 + "passiveEffectDuration": null,
3461 "priorityLevel": "Immediate",
3462 "timestamp": 0,
3463 },
@@ -3432,6 +3518,7 @@ Object {
3518 ],
3519 ],
3520 "duration": 0,
3521 + "effectDuration": null,
3522 "fiberActualDurations": Array [
3523 Array [
3524 5,
@@ -3493,6 +3580,7 @@ Object {
3580 ],
3581 ],
3582 "interactionIDs": Array [],
3583 + "passiveEffectDuration": null,
3584 "priorityLevel": "Immediate",
3585 "timestamp": 0,
3586 },
@@ -3552,6 +3640,7 @@ Object {
3640 ],
3641 ],
3642 "duration": 0,
3643 + "effectDuration": null,
3644 "fiberActualDurations": Array [
3645 Array [
3646 5,
@@ -3613,6 +3702,7 @@ Object {
3702 ],
3703 ],
3704 "interactionIDs": Array [],
3705 + "passiveEffectDuration": null,
3706 "priorityLevel": "Immediate",
3707 "timestamp": 0,
3708 },
@@ -3887,6 +3977,7 @@ Object {
3977 ],
3978 ],
3979 "duration": 11,
3980 + "effectDuration": null,
3981 "fiberActualDurations": Array [
3982 Array [
3983 1,
@@ -3926,6 +4017,7 @@ Object {
4017 "interactionIDs": Array [
4018 0,
4019 ],
4020 + "passiveEffectDuration": null,
4021 "priorityLevel": "Normal",
4022 "timestamp": 11,
4023 },
@@ -3965,6 +4057,7 @@ Object {
4057 ],
4058 ],
4059 "duration": 11,
4060 + "effectDuration": null,
4061 "fiberActualDurations": Array [
4062 Array [
4063 3,
@@ -4004,6 +4097,7 @@ Object {
4097 "interactionIDs": Array [
4098 1,
4099 ],
4100 + "passiveEffectDuration": null,
4101 "priorityLevel": "Immediate",
4102 "timestamp": 22,
4103 },
packages/react-devtools-shared/src/backend/renderer.js
+46
@@ -2097,6 +2097,25 @@ export function attach(
2097 // Checking root.memoizedInteractions handles multi-renderer edge-case-
2098 // where some v16 renderers support profiling and others don't.
2099 if (isProfiling && root.memoizedInteractions != null) {
2100 + // Profiling durations are only available for certain builds.
2101 + // If available, they'll be stored on the HostRoot.
2102 + let effectDuration = null;
2103 + let passiveEffectDuration = null;
2104 + const hostRoot = root.current;
2105 + if (hostRoot != null) {
2106 + const stateNode = hostRoot.stateNode;
2107 + if (stateNode != null) {
2108 + effectDuration =
2109 + stateNode.effectDuration != null
2110 + ? stateNode.effectDuration
2111 + : null;
2112 + passiveEffectDuration =
2113 + stateNode.passiveEffectDuration != null
2114 + ? stateNode.passiveEffectDuration
2115 + : null;
2116 + }
2117 + }
2118 +
2119 // If profiling is active, store commit time and duration, and the current interactions.
2120 // The frontend may request this information after profiling has stopped.
2121 currentCommitProfilingMetadata = {
@@ -2111,6 +2130,8 @@ export function attach(
2130 ),
2131 maxActualDuration: 0,
2132 priorityLevel: null,
2133 + effectDuration,
2134 + passiveEffectDuration,
2135 };
2136 }
2137
@@ -2149,6 +2170,23 @@ export function attach(
2170 const isProfilingSupported = root.memoizedInteractions != null;
2171
2172 if (isProfiling && isProfilingSupported) {
2173 + // Profiling durations are only available for certain builds.
2174 + // If available, they'll be stored on the HostRoot.
2175 + let effectDuration = null;
2176 + let passiveEffectDuration = null;
2177 + const hostRoot = root.current;
2178 + if (hostRoot != null) {
2179 + const stateNode = hostRoot.stateNode;
2180 + if (stateNode != null) {
2181 + effectDuration =
2182 + stateNode.effectDuration != null ? stateNode.effectDuration : null;
2183 + passiveEffectDuration =
2184 + stateNode.passiveEffectDuration != null
2185 + ? stateNode.passiveEffectDuration
2186 + : null;
2187 + }
2188 + }
2189 +
2190 // If profiling is active, store commit time and duration, and the current interactions.
2191 // The frontend may request this information after profiling has stopped.
2192 currentCommitProfilingMetadata = {
@@ -2164,6 +2202,8 @@ export function attach(
2202 maxActualDuration: 0,
2203 priorityLevel:
2204 priorityLevel == null ? null : formatPriorityLevel(priorityLevel),
2205 + effectDuration,
2206 + passiveEffectDuration,
2207 };
2208 }
2209
@@ -3294,8 +3334,10 @@ export function attach(
3334 changeDescriptions: Map<number, ChangeDescription> | null,
3335 commitTime: number,
3336 durations: Array<number>,
3337 + effectDuration: number | null,
3338 interactions: Array<Interaction>,
3339 maxActualDuration: number,
3340 + passiveEffectDuration: number | null,
3341 priorityLevel: string | null,
3342 |};
3343
@@ -3349,8 +3391,10 @@ export function attach(
3391 const {
3392 changeDescriptions,
3393 durations,
3394 + effectDuration,
3395 interactions,
3396 maxActualDuration,
3397 + passiveEffectDuration,
3398 priorityLevel,
3399 commitTime,
3400 } = commitProfilingData;
@@ -3386,9 +3430,11 @@ export function attach(
3430 ? Array.from(changeDescriptions.entries())
3431 : null,
3432 duration: maxActualDuration,
3433 + effectDuration,
3434 fiberActualDurations,
3435 fiberSelfDurations,
3436 interactionIDs,
3437 + passiveEffectDuration,
3438 priorityLevel,
3439 timestamp: commitTime,
3440 });
packages/react-devtools-shared/src/backend/types.js
+4
@@ -156,11 +156,15 @@ export type CommitDataBackend = {|
156 // Tuple of fiber ID and change description
157 changeDescriptions: Array<[number, ChangeDescription]> | null,
158 duration: number,
159 + // Only available in certain (newer) React builds,
160 + effectDuration: number | null,
161 // Tuple of fiber ID and actual duration
162 fiberActualDurations: Array<[number, number]>,
163 // Tuple of fiber ID and computed "self" duration
164 fiberSelfDurations: Array<[number, number]>,
165 interactionIDs: Array<number>,
166 + // Only available in certain (newer) React builds,
167 + passiveEffectDuration: number | null,
168 priorityLevel: string | null,
169 timestamp: number,
170 |};
packages/react-devtools-shared/src/devtools/views/Profiler/SidebarCommitInfo.css
+16
@@ -63,3 +63,19 @@
63 height: 100%;
64 color: var(--color-dim);
65 }
66 +
67 +.DurationsList {
68 + list-style: none;
69 + margin: 0.25rem 0 0 0;
70 + padding: 0;
71 + background: var(--color-background-inactive);
72 + padding: 0.25rem 0.5rem;
73 + border-radius: 0.25rem;
74 +}
75 +
76 +.DurationsListItem {
77 + margin: 0.25rem 0 0 0;
78 +}
79 +.DurationsListItem:first-of-type {
80 + margin: 0;
81 +}
packages/react-devtools-shared/src/devtools/views/Profiler/SidebarCommitInfo.js
+43 -4
@@ -34,7 +34,9 @@ export default function SidebarCommitInfo(_: Props) {
34 const {interactions} = profilerStore.getDataForRoot(rootID);
35 const {
36 duration,
37 + effectDuration,
38 interactionIDs,
39 + passiveEffectDuration,
40 priorityLevel,
41 timestamp,
42 } = profilerStore.getCommitData(rootID, selectedCommitIndex);
@@ -44,6 +46,9 @@ export default function SidebarCommitInfo(_: Props) {
46 selectInteraction(interactionID);
47 };
48
49 + const hasCommitPhaseDurations =
50 + effectDuration !== null || passiveEffectDuration !== null;
51 +
52 return (
53 <Fragment>
54 <div className={styles.Toolbar}>Commit information</div>
@@ -59,10 +64,44 @@ export default function SidebarCommitInfo(_: Props) {
64 <label className={styles.Label}>Committed at</label>:{' '}
65 <span className={styles.Value}>{formatTime(timestamp)}s</span>
66 </li>
62 - <li className={styles.ListItem}>
63 - <label className={styles.Label}>Render duration</label>:{' '}
64 - <span className={styles.Value}>{formatDuration(duration)}ms</span>
65 - </li>
67 +
68 + {!hasCommitPhaseDurations && (
69 + <li className={styles.ListItem}>
70 + <label className={styles.Label}>Render duration</label>:{' '}
71 + <span className={styles.Value}>{formatDuration(duration)}ms</span>
72 + </li>
73 + )}
74 +
75 + {hasCommitPhaseDurations && (
76 + <li className={styles.ListItem}>
77 + <label className={styles.Label}>Durations</label>
78 + <ul className={styles.DurationsList}>
79 + <li className={styles.DurationsListItem}>
80 + <label className={styles.Label}>Render</label>:{' '}
81 + <span className={styles.Value}>
82 + {formatDuration(duration)}ms
83 + </span>
84 + </li>
85 + {effectDuration !== null && (
86 + <li className={styles.DurationsListItem}>
87 + <label className={styles.Label}>Layout effects</label>:{' '}
88 + <span className={styles.Value}>
89 + {formatDuration(effectDuration)}ms
90 + </span>
91 + </li>
92 + )}
93 + {passiveEffectDuration !== null && (
94 + <li className={styles.DurationsListItem}>
95 + <label className={styles.Label}>Passive effects</label>:{' '}
96 + <span className={styles.Value}>
97 + {formatDuration(passiveEffectDuration)}ms
98 + </span>
99 + </li>
100 + )}
101 + </ul>
102 + </li>
103 + )}
104 +
105 <li className={styles.Interactions}>
106 <label className={styles.Label}>Interactions</label>:
107 <div className={styles.InteractionList}>
packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitList.css
+53
@@ -7,3 +7,56 @@
7 */
8 overflow-x: hidden !important;
9 }
10 +
11 +.Tooltip {
12 + margin-top: 2.5rem;
13 +}
14 +
15 +.TooltipList {
16 + list-style: none;
17 + padding: 0;
18 + margin: 0;
19 +}
20 +
21 +.TooltipListItem {
22 + display: flex;
23 +}
24 +
25 +.TooltipLabel {
26 + font-weight: bold;
27 + margin-right: 0.25rem;
28 +}
29 +.TooltipLabel:after {
30 + content: ':';
31 +}
32 +
33 +.TooltipValue {
34 + flex-grow: 1;
35 + text-align: end;
36 +}
37 +
38 +.DurationsWrapper {
39 + flex-grow: 1;
40 +}
41 +
42 +.DurationsList {
43 + list-style: none;
44 + margin: 0 0 0 1rem;
45 + padding: 0;
46 +}
47 +
48 +.DurationsListItem {
49 + display: flex;
50 +}
51 +
52 +.DurationsLabel {
53 + margin-right: 0.25rem;
54 +}
55 +.DurationsLabel:after {
56 + content: ':';
57 +}
58 +
59 +.DurationsValue {
60 + flex-grow: 1;
61 + text-align: end;
62 +}
\ No newline at end of file
packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitList.js
+83 -16
@@ -7,6 +7,8 @@
7 * @flow
8 */
9
10 +import type {CommitDataFrontend} from './types';
11 +
12 import * as React from 'react';
13 import {useEffect, useMemo, useRef, useState} from 'react';
14 import AutoSizer from 'react-virtualized-auto-sizer';
@@ -19,7 +21,6 @@ import Tooltip from './Tooltip';
21 import styles from './SnapshotCommitList.css';
22
23 export type ItemData = {|
22 - commitDurations: Array<number>,
24 commitTimes: Array<number>,
25 filteredCommitIndices: Array<number>,
26 maxDuration: number,
@@ -28,36 +29,40 @@ export type ItemData = {|
29 selectCommitIndex: (index: number) => void,
30 setHoveredCommitIndex: (index: number) => void,
31 startCommitDrag: (newDragState: DragState) => void,
32 + totalDurations: Array<number>,
33 |};
34
35 type Props = {|
34 - commitDurations: Array<number>,
36 + commitData: CommitDataFrontend,
37 commitTimes: Array<number>,
38 filteredCommitIndices: Array<number>,
39 selectedCommitIndex: number | null,
40 selectedFilteredCommitIndex: number | null,
41 selectCommitIndex: (index: number) => void,
42 + totalDurations: Array<number>,
43 |};
44
45 export default function SnapshotCommitList({
43 - commitDurations,
46 + commitData,
47 commitTimes,
48 filteredCommitIndices,
49 selectedCommitIndex,
50 selectedFilteredCommitIndex,
51 selectCommitIndex,
52 + totalDurations,
53 }: Props) {
54 return (
55 <AutoSizer>
56 {({height, width}) => (
57 <List
54 - commitDurations={commitDurations}
58 + commitData={commitData}
59 commitTimes={commitTimes}
60 height={height}
61 filteredCommitIndices={filteredCommitIndices}
62 selectedCommitIndex={selectedCommitIndex}
63 selectedFilteredCommitIndex={selectedFilteredCommitIndex}
64 selectCommitIndex={selectCommitIndex}
65 + totalDurations={totalDurations}
66 width={width}
67 />
68 )}
@@ -66,13 +71,14 @@ export default function SnapshotCommitList({
71 }
72
73 type ListProps = {|
69 - commitDurations: Array<number>,
74 + commitData: CommitDataFrontend,
75 commitTimes: Array<number>,
76 height: number,
77 filteredCommitIndices: Array<number>,
78 selectedCommitIndex: number | null,
79 selectedFilteredCommitIndex: number | null,
80 selectCommitIndex: (index: number) => void,
81 + totalDurations: Array<number>,
82 width: number,
83 |};
84
@@ -83,13 +89,14 @@ type DragState = {
89 };
90
91 function List({
86 - commitDurations,
92 + commitData,
93 selectedCommitIndex,
94 commitTimes,
95 height,
96 filteredCommitIndices,
97 selectedFilteredCommitIndex,
98 selectCommitIndex,
99 + totalDurations,
100 width,
101 }: ListProps) {
102 const listRef = useRef<FixedSizeList<ItemData> | null>(null);
@@ -111,8 +118,8 @@ function List({
118 [filteredCommitIndices, width],
119 );
120 const maxDuration = useMemo(
114 - () => commitDurations.reduce((max, duration) => Math.max(max, duration), 0),
115 - [commitDurations],
121 + () => totalDurations.reduce((max, duration) => Math.max(max, duration), 0),
122 + [totalDurations],
123 );
124
125 const maxCommitIndex = filteredCommitIndices.length - 1;
@@ -176,7 +183,6 @@ function List({
183 // Pass required contextual data down to the ListItem renderer.
184 const itemData = useMemo<ItemData>(
185 () => ({
179 - commitDurations,
186 commitTimes,
187 filteredCommitIndices,
188 maxDuration,
@@ -185,9 +191,9 @@ function List({
191 selectCommitIndex,
192 setHoveredCommitIndex,
193 startCommitDrag: setDragState,
194 + totalDurations,
195 }),
196 [
190 - commitDurations,
197 commitTimes,
198 filteredCommitIndices,
199 maxDuration,
@@ -195,20 +201,81 @@ function List({
201 selectedFilteredCommitIndex,
202 selectCommitIndex,
203 setHoveredCommitIndex,
204 + totalDurations,
205 ],
206 );
207
208 let tooltipLabel = null;
209 if (hoveredCommitIndex !== null) {
203 - const commitDuration = commitDurations[hoveredCommitIndex];
204 - const commitTime = commitTimes[hoveredCommitIndex];
205 - tooltipLabel = `${formatDuration(commitDuration)}ms at ${formatTime(
206 - commitTime,
207 - )}s`;
210 + const {
211 + duration,
212 + effectDuration,
213 + passiveEffectDuration,
214 + priorityLevel,
215 + timestamp,
216 + } = commitData[hoveredCommitIndex];
217 +
218 + // Only some React versions include commit durations.
219 + // Show a richer tooltip only for builds that have that info.
220 + if (effectDuration !== null || passiveEffectDuration !== null) {
221 + tooltipLabel = (
222 + <ul className={styles.TooltipList}>
223 + {priorityLevel !== null && (
224 + <li className={styles.TooltipListItem}>
225 + <label className={styles.TooltipLabel}>Priority</label>
226 + <span className={styles.TooltipValue}>{priorityLevel}</span>
227 + </li>
228 + )}
229 + <li className={styles.TooltipListItem}>
230 + <label className={styles.TooltipLabel}>Committed at</label>
231 + <span className={styles.TooltipValue}>
232 + {formatTime(timestamp)}s
233 + </span>
234 + </li>
235 + <li className={styles.TooltipListItem}>
236 + <div className={styles.DurationsWrapper}>
237 + <label className={styles.TooltipLabel}>Durations</label>
238 + <ul className={styles.DurationsList}>
239 + <li className={styles.DurationsListItem}>
240 + <label className={styles.DurationsLabel}>Render</label>
241 + <span className={styles.DurationsValue}>
242 + {formatDuration(duration)}ms
243 + </span>
244 + </li>
245 + {effectDuration !== null && (
246 + <li className={styles.DurationsListItem}>
247 + <label className={styles.DurationsLabel}>
248 + Layout effects
249 + </label>
250 + <span className={styles.DurationsValue}>
251 + {formatDuration(effectDuration)}ms
252 + </span>
253 + </li>
254 + )}
255 + {passiveEffectDuration !== null && (
256 + <li className={styles.DurationsListItem}>
257 + <label className={styles.DurationsLabel}>
258 + Passive effects
259 + </label>
260 + <span className={styles.DurationsValue}>
261 + {formatDuration(passiveEffectDuration)}ms
262 + </span>
263 + </li>
264 + )}
265 + </ul>
266 + </div>
267 + </li>
268 + </ul>
269 + );
270 + } else {
271 + tooltipLabel = `${formatDuration(duration)}ms at ${formatTime(
272 + timestamp,
273 + )}s`;
274 + }
275 }
276
277 return (
211 - <Tooltip label={tooltipLabel}>
278 + <Tooltip className={styles.Tooltip} label={tooltipLabel}>
279 <div
280 ref={divRef}
281 style={{height, width}}
packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitListItem.css
+6 -1
@@ -11,9 +11,14 @@
11 background-color: var(--color-background);
12 }
13
14 -.Inner {
14 +.Inner,
15 +.InnerSelected {
16 width: 100%;
17 min-height: 2px;
18 background-color: var(--color-commit-did-not-render-fill);
19 color: var(--color-commit-did-not-render-fill-text);
20 }
21 +
22 +.InnerSelected {
23 + background-color: var(--color-button-active);
24 +}
\ No newline at end of file
packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitListItem.js
+13 -15
@@ -10,7 +10,7 @@
10 import * as React from 'react';
11 import {memo} from 'react';
12 import {areEqual} from 'react-window';
13 -import {getGradientColor, formatDuration, formatTime} from './utils';
13 +import {getGradientColor} from './utils';
14
15 import styles from './SnapshotCommitListItem.css';
16
@@ -25,20 +25,18 @@ type Props = {
25
26 function SnapshotCommitListItem({data: itemData, index, style}: Props) {
27 const {
28 - commitDurations,
29 - commitTimes,
28 filteredCommitIndices,
29 maxDuration,
30 selectedCommitIndex,
31 selectCommitIndex,
32 setHoveredCommitIndex,
33 startCommitDrag,
34 + totalDurations,
35 } = itemData;
36
37 index = filteredCommitIndices[index];
38
40 - const commitDuration = commitDurations[index];
41 - const commitTime = commitTimes[index];
39 + const totalDuration = totalDurations[index];
40
41 // Use natural cbrt for bar height.
42 // This prevents one (or a few) outliers from squishing the majority of other commits.
@@ -46,14 +44,13 @@ function SnapshotCommitListItem({data: itemData, index, style}: Props) {
44 const heightScale =
45 Math.min(
46 1,
49 - Math.max(0, Math.cbrt(commitDuration) / Math.cbrt(maxDuration)),
47 + Math.max(0, Math.cbrt(totalDuration) / Math.cbrt(maxDuration)),
48 ) || 0;
49
50 // Use a linear scale for color.
51 // This gives some visual contrast between cheaper and more expensive commits
52 // and somewhat compensates for the cbrt scale height.
55 - const colorScale =
56 - Math.min(1, Math.max(0, commitDuration / maxDuration)) || 0;
53 + const colorScale = Math.min(1, Math.max(0, totalDuration / maxDuration)) || 0;
54
55 const isSelected = selectedCommitIndex === index;
56
@@ -71,6 +68,11 @@ function SnapshotCommitListItem({data: itemData, index, style}: Props) {
68 }
69 };
70
71 + let backgroundColor;
72 + if (!isSelected && totalDuration > 0) {
73 + backgroundColor = getGradientColor(colorScale);
74 + }
75 +
76 return (
77 <div
78 className={styles.Outer}
@@ -82,16 +84,12 @@ function SnapshotCommitListItem({data: itemData, index, style}: Props) {
84 borderBottom: isSelected
85 ? '3px solid var(--color-tab-selected-border)'
86 : undefined,
85 - }}
86 - title={`Duration ${formatDuration(commitDuration)}ms at ${formatTime(
87 - commitTime,
88 - )}s`}>
87 + }}>
88 <div
90 - className={styles.Inner}
89 + className={isSelected ? styles.InnerSelected : styles.Inner}
90 style={{
91 height: `${Math.round(heightScale * 100)}%`,
93 - backgroundColor:
94 - commitDuration > 0 ? getGradientColor(colorScale) : undefined,
92 + backgroundColor,
93 }}
94 />
95 </div>
packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotSelector.js
+8 -3
@@ -32,10 +32,14 @@ export default function SnapshotSelector(_: Props) {
32 const {profilerStore} = useContext(StoreContext);
33 const {commitData} = profilerStore.getDataForRoot(((rootID: any): number));
34
35 - const commitDurations: Array<number> = [];
35 + const totalDurations: Array<number> = [];
36 const commitTimes: Array<number> = [];
37 commitData.forEach(commitDatum => {
38 - commitDurations.push(commitDatum.duration);
38 + totalDurations.push(
39 + commitDatum.duration +
40 + (commitDatum.effectDuration || 0) +
41 + (commitDatum.passiveEffectDuration || 0),
42 + );
43 commitTimes.push(commitDatum.timestamp);
44 });
45
@@ -151,12 +155,13 @@ export default function SnapshotSelector(_: Props) {
155 tabIndex={0}>
156 {numFilteredCommits > 0 && (
157 <SnapshotCommitList
154 - commitDurations={commitDurations}
158 + commitData={commitData}
159 commitTimes={commitTimes}
160 filteredCommitIndices={filteredCommitIndices}
161 selectedCommitIndex={selectedCommitIndex}
162 selectedFilteredCommitIndex={selectedFilteredCommitIndex}
163 selectCommitIndex={selectCommitIndex}
164 + totalDurations={totalDurations}
165 />
166 )}
167 {numFilteredCommits === 0 && (
packages/react-devtools-shared/src/devtools/views/Profiler/Tooltip.js
+5 -2
@@ -7,7 +7,7 @@ import styles from './Tooltip.css';
7
8 const initialTooltipState = {height: 0, mouseX: 0, mouseY: 0, width: 0};
9
10 -export default function Tooltip({children, label}: any) {
10 +export default function Tooltip({children, className, label, style}: any) {
11 const containerRef = useRef(null);
12 const tooltipRef = useRef(null);
13
@@ -36,7 +36,10 @@ export default function Tooltip({children, label}: any) {
36 className={styles.Container}
37 onMouseMove={onMouseMove}
38 ref={containerRef}>
39 - <div ref={tooltipRef} className={`${styles.Tooltip} ${tooltipClassName}`}>
39 + <div
40 + className={`${styles.Tooltip} ${tooltipClassName} ${className || ''}`}
41 + ref={tooltipRef}
42 + style={style}>
43 {label}
44 </div>
45 {children}
packages/react-devtools-shared/src/devtools/views/Profiler/types.js
+11 -1
@@ -52,9 +52,13 @@ export type CommitDataFrontend = {|
52 // Map of Fiber (ID) to a description of what changed in this commit.
53 changeDescriptions: Map<number, ChangeDescription> | null,
54
55 - // How long was this commit?
55 + // How long was the render phase?
56 duration: number,
57
58 + // How long was the layout commit phase?
59 + // Note that not all builds of React expose this property.
60 + effectDuration: number | null,
61 +
62 // Map of Fiber (ID) to actual duration for this commit;
63 // Fibers that did not render will not have entries in this Map.
64 fiberActualDurations: Map<number, number>,
@@ -66,6 +70,10 @@ export type CommitDataFrontend = {|
70 // Which interactions (IDs) were associated with this commit.
71 interactionIDs: Array<number>,
72
73 + // How long was the passive commit phase?
74 + // Note that not all builds of React expose this property.
75 + passiveEffectDuration: number | null,
76 +
77 // Priority level of the commit (if React provided this info)
78 priorityLevel: string | null,
79
@@ -113,11 +121,13 @@ export type ProfilingDataFrontend = {|
121 export type CommitDataExport = {|
122 changeDescriptions: Array<[number, ChangeDescription]> | null,
123 duration: number,
124 + effectDuration: number | null,
125 // Tuple of fiber ID and actual duration
126 fiberActualDurations: Array<[number, number]>,
127 // Tuple of fiber ID and computed "self" duration
128 fiberSelfDurations: Array<[number, number]>,
129 interactionIDs: Array<number>,
130 + passiveEffectDuration: number | null,
131 priorityLevel: string | null,
132 timestamp: number,
133 |};
packages/react-devtools-shared/src/devtools/views/Profiler/utils.js
+10
@@ -75,11 +75,13 @@ export function prepareProfilingDataFrontendFromBackendAndStore(
75 ? new Map(commitDataBackend.changeDescriptions)
76 : null,
77 duration: commitDataBackend.duration,
78 + effectDuration: commitDataBackend.effectDuration,
79 fiberActualDurations: new Map(
80 commitDataBackend.fiberActualDurations,
81 ),
82 fiberSelfDurations: new Map(commitDataBackend.fiberSelfDurations),
83 interactionIDs: commitDataBackend.interactionIDs,
84 + passiveEffectDuration: commitDataBackend.passiveEffectDuration,
85 priorityLevel: commitDataBackend.priorityLevel,
86 timestamp: commitDataBackend.timestamp,
87 }),
@@ -129,18 +131,22 @@ export function prepareProfilingDataFrontendFromExport(
131 ({
132 changeDescriptions,
133 duration,
134 + effectDuration,
135 fiberActualDurations,
136 fiberSelfDurations,
137 interactionIDs,
138 + passiveEffectDuration,
139 priorityLevel,
140 timestamp,
141 }) => ({
142 changeDescriptions:
143 changeDescriptions != null ? new Map(changeDescriptions) : null,
144 duration,
145 + effectDuration,
146 fiberActualDurations: new Map(fiberActualDurations),
147 fiberSelfDurations: new Map(fiberSelfDurations),
148 interactionIDs,
149 + passiveEffectDuration,
150 priorityLevel,
151 timestamp,
152 }),
@@ -180,9 +186,11 @@ export function prepareProfilingDataExport(
186 ({
187 changeDescriptions,
188 duration,
189 + effectDuration,
190 fiberActualDurations,
191 fiberSelfDurations,
192 interactionIDs,
193 + passiveEffectDuration,
194 priorityLevel,
195 timestamp,
196 }) => ({
@@ -191,9 +199,11 @@ export function prepareProfilingDataExport(
199 ? Array.from(changeDescriptions.entries())
200 : null,
201 duration,
202 + effectDuration,
203 fiberActualDurations: Array.from(fiberActualDurations.entries()),
204 fiberSelfDurations: Array.from(fiberSelfDurations.entries()),
205 interactionIDs,
206 + passiveEffectDuration,
207 priorityLevel,
208 timestamp,
209 }),
packages/react-devtools-shell/src/app/InteractionTracing/index.js
+11 -1
@@ -8,7 +8,13 @@
8 */
9
10 import * as React from 'react';
11 -import {Fragment, useCallback, useEffect, useState} from 'react';
11 +import {
12 + Fragment,
13 + useCallback,
14 + useLayoutEffect,
15 + useEffect,
16 + useState,
17 +} from 'react';
18 import {unstable_batchedUpdates as batchedUpdates} from 'react-dom';
19 import {
20 unstable_trace as trace,
@@ -68,6 +74,10 @@ export default function InteractionTracing() {
74 }
75 }, [count, shouldCascade]);
76
77 + useLayoutEffect(() => {
78 + Math.sqrt(100 * 100 * 100 * 100 * 100);
79 + });
80 +
81 return (
82 <Fragment>
83 <h1>Interaction Tracing</h1>