devtools: emit performance entries only when profiling (#33652)
## Summary This floods Timings track in dev mode and also hurts performance in dev. Making sure we are buffering Performance entries (all of them are marks) only when profiling in RDT. This should be removed once we roll out Perf tracks.
Ruslan Lesiutin committed
Jun 27, 2025 at 15:32 UTC
58ac15cdc953a21ac1b352b6300abc3da87fa3d6
1 file changed
+119
-147
packages/react-devtools-shared/src/backend/profilingHooks.js
+119
-147
@@ -329,21 +329,17 @@ export function createProfilingHooks({
329
}
330
331
function markComponentRenderStarted(fiber: Fiber): void {
332
- if (isProfiling || supportsUserTimingV3) {
332
+ if (isProfiling) {
333
const componentName = getDisplayNameForFiber(fiber) || 'Unknown';
334
335
- if (isProfiling) {
336
- // TODO (timeline) Record and cache component stack
337
- if (isProfiling) {
338
- currentReactComponentMeasure = {
339
- componentName,
340
- duration: 0,
341
- timestamp: getRelativeTime(),
342
- type: 'render',
343
- warning: null,
344
- };
345
- }
346
- }
335
+ // TODO (timeline) Record and cache component stack
336
+ currentReactComponentMeasure = {
337
+ componentName,
338
+ duration: 0,
339
+ timestamp: getRelativeTime(),
340
+ type: 'render',
341
+ warning: null,
342
+ };
343
344
if (supportsUserTimingV3) {
345
markAndClear(`--component-render-start-${componentName}`);
@@ -374,21 +370,17 @@ export function createProfilingHooks({
370
}
371
372
function markComponentLayoutEffectMountStarted(fiber: Fiber): void {
377
- if (isProfiling || supportsUserTimingV3) {
373
+ if (isProfiling) {
374
const componentName = getDisplayNameForFiber(fiber) || 'Unknown';
375
380
- if (isProfiling) {
381
- // TODO (timeline) Record and cache component stack
382
- if (isProfiling) {
383
- currentReactComponentMeasure = {
384
- componentName,
385
- duration: 0,
386
- timestamp: getRelativeTime(),
387
- type: 'layout-effect-mount',
388
- warning: null,
389
- };
390
- }
391
- }
376
+ // TODO (timeline) Record and cache component stack
377
+ currentReactComponentMeasure = {
378
+ componentName,
379
+ duration: 0,
380
+ timestamp: getRelativeTime(),
381
+ type: 'layout-effect-mount',
382
+ warning: null,
383
+ };
384
385
if (supportsUserTimingV3) {
386
markAndClear(`--component-layout-effect-mount-start-${componentName}`);
@@ -419,21 +411,17 @@ export function createProfilingHooks({
411
}
412
413
function markComponentLayoutEffectUnmountStarted(fiber: Fiber): void {
422
- if (isProfiling || supportsUserTimingV3) {
414
+ if (isProfiling) {
415
const componentName = getDisplayNameForFiber(fiber) || 'Unknown';
416
425
- if (isProfiling) {
426
- // TODO (timeline) Record and cache component stack
427
- if (isProfiling) {
428
- currentReactComponentMeasure = {
429
- componentName,
430
- duration: 0,
431
- timestamp: getRelativeTime(),
432
- type: 'layout-effect-unmount',
433
- warning: null,
434
- };
435
- }
436
- }
417
+ // TODO (timeline) Record and cache component stack
418
+ currentReactComponentMeasure = {
419
+ componentName,
420
+ duration: 0,
421
+ timestamp: getRelativeTime(),
422
+ type: 'layout-effect-unmount',
423
+ warning: null,
424
+ };
425
426
if (supportsUserTimingV3) {
427
markAndClear(
@@ -466,21 +454,17 @@ export function createProfilingHooks({
454
}
455
456
function markComponentPassiveEffectMountStarted(fiber: Fiber): void {
469
- if (isProfiling || supportsUserTimingV3) {
457
+ if (isProfiling) {
458
const componentName = getDisplayNameForFiber(fiber) || 'Unknown';
459
472
- if (isProfiling) {
473
- // TODO (timeline) Record and cache component stack
474
- if (isProfiling) {
475
- currentReactComponentMeasure = {
476
- componentName,
477
- duration: 0,
478
- timestamp: getRelativeTime(),
479
- type: 'passive-effect-mount',
480
- warning: null,
481
- };
482
- }
483
- }
460
+ // TODO (timeline) Record and cache component stack
461
+ currentReactComponentMeasure = {
462
+ componentName,
463
+ duration: 0,
464
+ timestamp: getRelativeTime(),
465
+ type: 'passive-effect-mount',
466
+ warning: null,
467
+ };
468
469
if (supportsUserTimingV3) {
470
markAndClear(`--component-passive-effect-mount-start-${componentName}`);
@@ -511,21 +495,17 @@ export function createProfilingHooks({
495
}
496
497
function markComponentPassiveEffectUnmountStarted(fiber: Fiber): void {
514
- if (isProfiling || supportsUserTimingV3) {
498
+ if (isProfiling) {
499
const componentName = getDisplayNameForFiber(fiber) || 'Unknown';
500
517
- if (isProfiling) {
518
- // TODO (timeline) Record and cache component stack
519
- if (isProfiling) {
520
- currentReactComponentMeasure = {
521
- componentName,
522
- duration: 0,
523
- timestamp: getRelativeTime(),
524
- type: 'passive-effect-unmount',
525
- warning: null,
526
- };
527
- }
528
- }
501
+ // TODO (timeline) Record and cache component stack
502
+ currentReactComponentMeasure = {
503
+ componentName,
504
+ duration: 0,
505
+ timestamp: getRelativeTime(),
506
+ type: 'passive-effect-unmount',
507
+ warning: null,
508
+ };
509
510
if (supportsUserTimingV3) {
511
markAndClear(
@@ -562,7 +542,7 @@ export function createProfilingHooks({
542
thrownValue: mixed,
543
lanes: Lanes,
544
): void {
565
- if (isProfiling || supportsUserTimingV3) {
545
+ if (isProfiling) {
546
const componentName = getDisplayNameForFiber(fiber) || 'Unknown';
547
const phase = fiber.alternate === null ? 'mount' : 'update';
548
@@ -577,17 +557,15 @@ export function createProfilingHooks({
557
message = thrownValue;
558
}
559
580
- if (isProfiling) {
581
- // TODO (timeline) Record and cache component stack
582
- if (currentTimelineData) {
583
- currentTimelineData.thrownErrors.push({
584
- componentName,
585
- message,
586
- phase,
587
- timestamp: getRelativeTime(),
588
- type: 'thrown-error',
589
- });
590
- }
560
+ // TODO (timeline) Record and cache component stack
561
+ if (currentTimelineData) {
562
+ currentTimelineData.thrownErrors.push({
563
+ componentName,
564
+ message,
565
+ phase,
566
+ timestamp: getRelativeTime(),
567
+ type: 'thrown-error',
568
+ });
569
}
570
571
if (supportsUserTimingV3) {
@@ -613,7 +591,7 @@ export function createProfilingHooks({
591
wakeable: Wakeable,
592
lanes: Lanes,
593
): void {
616
- if (isProfiling || supportsUserTimingV3) {
594
+ if (isProfiling) {
595
const eventType = wakeableIDs.has(wakeable) ? 'resuspend' : 'suspend';
596
const id = getWakeableID(wakeable);
597
const componentName = getDisplayNameForFiber(fiber) || 'Unknown';
@@ -626,56 +604,54 @@ export function createProfilingHooks({
604
const displayName = (wakeable: any).displayName || '';
605
606
let suspenseEvent: SuspenseEvent | null = null;
629
- if (isProfiling) {
630
- // TODO (timeline) Record and cache component stack
631
- suspenseEvent = {
632
- componentName,
633
- depth: 0,
634
- duration: 0,
635
- id: `${id}`,
636
- phase,
637
- promiseName: displayName,
638
- resolution: 'unresolved',
639
- timestamp: getRelativeTime(),
640
- type: 'suspense',
641
- warning: null,
642
- };
607
+ // TODO (timeline) Record and cache component stack
608
+ suspenseEvent = {
609
+ componentName,
610
+ depth: 0,
611
+ duration: 0,
612
+ id: `${id}`,
613
+ phase,
614
+ promiseName: displayName,
615
+ resolution: 'unresolved',
616
+ timestamp: getRelativeTime(),
617
+ type: 'suspense',
618
+ warning: null,
619
+ };
620
644
- if (currentTimelineData) {
645
- currentTimelineData.suspenseEvents.push(suspenseEvent);
646
- }
621
+ if (currentTimelineData) {
622
+ currentTimelineData.suspenseEvents.push(suspenseEvent);
623
}
624
625
if (supportsUserTimingV3) {
626
markAndClear(
627
`--suspense-${eventType}-${id}-${componentName}-${phase}-${lanes}-${displayName}`,
628
);
653
- }
629
655
- wakeable.then(
656
- () => {
657
- if (suspenseEvent) {
658
- suspenseEvent.duration =
659
- getRelativeTime() - suspenseEvent.timestamp;
660
- suspenseEvent.resolution = 'resolved';
661
- }
630
+ wakeable.then(
631
+ () => {
632
+ if (suspenseEvent) {
633
+ suspenseEvent.duration =
634
+ getRelativeTime() - suspenseEvent.timestamp;
635
+ suspenseEvent.resolution = 'resolved';
636
+ }
637
663
- if (supportsUserTimingV3) {
664
- markAndClear(`--suspense-resolved-${id}-${componentName}`);
665
- }
666
- },
667
- () => {
668
- if (suspenseEvent) {
669
- suspenseEvent.duration =
670
- getRelativeTime() - suspenseEvent.timestamp;
671
- suspenseEvent.resolution = 'rejected';
672
- }
638
+ if (supportsUserTimingV3) {
639
+ markAndClear(`--suspense-resolved-${id}-${componentName}`);
640
+ }
641
+ },
642
+ () => {
643
+ if (suspenseEvent) {
644
+ suspenseEvent.duration =
645
+ getRelativeTime() - suspenseEvent.timestamp;
646
+ suspenseEvent.resolution = 'rejected';
647
+ }
648
674
- if (supportsUserTimingV3) {
675
- markAndClear(`--suspense-rejected-${id}-${componentName}`);
676
- }
677
- },
678
- );
649
+ if (supportsUserTimingV3) {
650
+ markAndClear(`--suspense-rejected-${id}-${componentName}`);
651
+ }
652
+ },
653
+ );
654
+ }
655
}
656
}
657
@@ -782,20 +758,18 @@ export function createProfilingHooks({
758
}
759
760
function markForceUpdateScheduled(fiber: Fiber, lane: Lane): void {
785
- if (isProfiling || supportsUserTimingV3) {
761
+ if (isProfiling) {
762
const componentName = getDisplayNameForFiber(fiber) || 'Unknown';
763
788
- if (isProfiling) {
789
- // TODO (timeline) Record and cache component stack
790
- if (currentTimelineData) {
791
- currentTimelineData.schedulingEvents.push({
792
- componentName,
793
- lanes: laneToLanesArray(lane),
794
- timestamp: getRelativeTime(),
795
- type: 'schedule-force-update',
796
- warning: null,
797
- });
798
- }
764
+ // TODO (timeline) Record and cache component stack
765
+ if (currentTimelineData) {
766
+ currentTimelineData.schedulingEvents.push({
767
+ componentName,
768
+ lanes: laneToLanesArray(lane),
769
+ timestamp: getRelativeTime(),
770
+ type: 'schedule-force-update',
771
+ warning: null,
772
+ });
773
}
774
775
if (supportsUserTimingV3) {
@@ -815,25 +789,23 @@ export function createProfilingHooks({
789
}
790
791
function markStateUpdateScheduled(fiber: Fiber, lane: Lane): void {
818
- if (isProfiling || supportsUserTimingV3) {
792
+ if (isProfiling) {
793
const componentName = getDisplayNameForFiber(fiber) || 'Unknown';
794
821
- if (isProfiling) {
822
- // TODO (timeline) Record and cache component stack
823
- if (currentTimelineData) {
824
- const event: ReactScheduleStateUpdateEvent = {
825
- componentName,
826
- // Store the parent fibers so we can post process
827
- // them after we finish profiling
828
- lanes: laneToLanesArray(lane),
829
- timestamp: getRelativeTime(),
830
- type: 'schedule-state-update',
831
- warning: null,
832
- };
833
- currentFiberStacks.set(event, getParentFibers(fiber));
834
- // $FlowFixMe[incompatible-use] found when upgrading Flow
835
- currentTimelineData.schedulingEvents.push(event);
836
- }
795
+ // TODO (timeline) Record and cache component stack
796
+ if (currentTimelineData) {
797
+ const event: ReactScheduleStateUpdateEvent = {
798
+ componentName,
799
+ // Store the parent fibers so we can post process
800
+ // them after we finish profiling
801
+ lanes: laneToLanesArray(lane),
802
+ timestamp: getRelativeTime(),
803
+ type: 'schedule-state-update',
804
+ warning: null,
805
+ };
806
+ currentFiberStacks.set(event, getParentFibers(fiber));
807
+ // $FlowFixMe[incompatible-use] found when upgrading Flow
808
+ currentTimelineData.schedulingEvents.push(event);
809
}
810
811
if (supportsUserTimingV3) {