@@ -112,15 +112,9 @@ import {
112
112
import { popProvider , resetContextDependences } from './ReactFiberNewContext' ;
113
113
import { popHostContext , popHostContainer } from './ReactFiberHostContext' ;
114
114
import {
115
- checkActualRenderTimeStackEmpty ,
116
- pauseActualRenderTimerIfRunning ,
117
115
recordCommitTime ,
118
- recordElapsedActualRenderTime ,
119
- recordElapsedBaseRenderTimeIfRunning ,
120
- resetActualRenderTimerStackAfterFatalErrorInDev ,
121
- resumeActualRenderTimerIfPaused ,
122
- startBaseRenderTimer ,
123
- stopBaseRenderTimerIfRunning ,
116
+ startProfilerTimer ,
117
+ stopProfilerTimerIfRunningAndRecordDelta ,
124
118
} from './ReactProfilerTimer' ;
125
119
import {
126
120
checkThatStackIsEmpty ,
@@ -312,15 +306,6 @@ if (__DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback) {
312
306
originalReplayError = null ;
313
307
if ( hasCaughtError ( ) ) {
314
308
clearCaughtError ( ) ;
315
-
316
- if ( enableProfilerTimer ) {
317
- if ( failedUnitOfWork . mode & ProfileMode ) {
318
- recordElapsedActualRenderTime ( failedUnitOfWork ) ;
319
- }
320
-
321
- // Stop "base" render timer again (after the re-thrown error).
322
- stopBaseRenderTimerIfRunning ( ) ;
323
- }
324
309
} else {
325
310
// If the begin phase did not fail the second time, set this pointer
326
311
// back to the original value.
@@ -336,12 +321,6 @@ function resetStack() {
336
321
if ( nextUnitOfWork !== null ) {
337
322
let interruptedWork = nextUnitOfWork . return ;
338
323
while ( interruptedWork !== null ) {
339
- if ( enableProfilerTimer ) {
340
- if ( interruptedWork . mode & ProfileMode ) {
341
- // Resume in case we're picking up on work that was paused.
342
- resumeActualRenderTimerIfPaused ( false ) ;
343
- }
344
- }
345
324
unwindInterruptedWork ( interruptedWork ) ;
346
325
interruptedWork = interruptedWork . return ;
347
326
}
@@ -691,17 +670,6 @@ function commitRoot(root: FiberRoot, finishedWork: Fiber): void {
691
670
}
692
671
}
693
672
694
- if ( enableProfilerTimer ) {
695
- if ( __DEV__ ) {
696
- if ( nextRoot === null ) {
697
- // Only check this stack once we're done processing async work.
698
- // This prevents a false positive that occurs after a batched commit,
699
- // If there was in-progress async work before the commit.
700
- checkActualRenderTimeStackEmpty ( ) ;
701
- }
702
- }
703
- }
704
-
705
673
isCommitting = false ;
706
674
isWorking = false ;
707
675
stopCommitLifeCyclesTimer ( ) ;
@@ -741,9 +709,22 @@ function resetChildExpirationTime(
741
709
742
710
// Bubble up the earliest expiration time.
743
711
if ( enableProfilerTimer && workInProgress . mode & ProfileMode ) {
744
- // We're in profiling mode. Let's use this same traversal to update the
745
- // "base" render times.
712
+ // We're in profiling mode.
713
+ // Let's use this same traversal to update the render durations.
714
+ let actualDuration = workInProgress . actualDuration ;
746
715
let treeBaseDuration = workInProgress . selfBaseDuration ;
716
+
717
+ // When a fiber is cloned, its actualDuration is reset to 0.
718
+ // This value will only be updated if work is done on the fiber (i.e. it doesn't bailout).
719
+ // When work is done, it should bubble to the parent's actualDuration.
720
+ // If the fiber has not been cloned though, (meaning no work was done),
721
+ // Then this value will reflect the amount of time spent working on a previous render.
722
+ // In that case it should not bubble.
723
+ // We determine whether it was cloned by comparing the child pointer.
724
+ const shouldBubbleActualDurations =
725
+ workInProgress . alternate === null ||
726
+ workInProgress . child !== workInProgress . alternate . child ;
727
+
747
728
let child = workInProgress . child ;
748
729
while ( child !== null ) {
749
730
const childUpdateExpirationTime = child . expirationTime ;
@@ -762,9 +743,13 @@ function resetChildExpirationTime(
762
743
) {
763
744
newChildExpirationTime = childChildExpirationTime ;
764
745
}
746
+ if ( shouldBubbleActualDurations ) {
747
+ actualDuration += child . actualDuration ;
748
+ }
765
749
treeBaseDuration += child . treeBaseDuration ;
766
750
child = child . sibling ;
767
751
}
752
+ workInProgress . actualDuration = actualDuration ;
768
753
workInProgress . treeBaseDuration = treeBaseDuration ;
769
754
} else {
770
755
let child = workInProgress . child ;
@@ -811,11 +796,28 @@ function completeUnitOfWork(workInProgress: Fiber): Fiber | null {
811
796
812
797
if ( ( workInProgress . effectTag & Incomplete ) === NoEffect ) {
813
798
// This fiber completed.
814
- nextUnitOfWork = completeWork (
815
- current ,
816
- workInProgress ,
817
- nextRenderExpirationTime ,
818
- ) ;
799
+ if ( enableProfilerTimer ) {
800
+ if ( workInProgress . mode & ProfileMode ) {
801
+ startProfilerTimer ( workInProgress ) ;
802
+ }
803
+
804
+ nextUnitOfWork = completeWork (
805
+ current ,
806
+ workInProgress ,
807
+ nextRenderExpirationTime ,
808
+ ) ;
809
+
810
+ if ( workInProgress . mode & ProfileMode ) {
811
+ // Update render duration assuming we didn't error.
812
+ stopProfilerTimerIfRunningAndRecordDelta ( workInProgress , false ) ;
813
+ }
814
+ } else {
815
+ nextUnitOfWork = completeWork (
816
+ current ,
817
+ workInProgress ,
818
+ nextRenderExpirationTime ,
819
+ ) ;
820
+ }
819
821
let next = nextUnitOfWork ;
820
822
stopWorkTimer ( workInProgress ) ;
821
823
resetChildExpirationTime ( workInProgress , nextRenderExpirationTime ) ;
@@ -886,6 +888,11 @@ function completeUnitOfWork(workInProgress: Fiber): Fiber | null {
886
888
return null ;
887
889
}
888
890
} else {
891
+ if ( workInProgress . mode & ProfileMode ) {
892
+ // Record the render duration for the fiber that errored.
893
+ stopProfilerTimerIfRunningAndRecordDelta ( workInProgress , false ) ;
894
+ }
895
+
889
896
// This fiber did not complete because something threw. Pop values off
890
897
// the stack without entering the complete phase. If this is a boundary,
891
898
// capture values if possible.
@@ -908,6 +915,19 @@ function completeUnitOfWork(workInProgress: Fiber): Fiber | null {
908
915
ReactFiberInstrumentation . debugTool . onCompleteWork ( workInProgress ) ;
909
916
}
910
917
918
+ if ( enableProfilerTimer ) {
919
+ // Include the time spent working on failed children before continuing.
920
+ if ( next . mode & ProfileMode ) {
921
+ let actualDuration = next . actualDuration ;
922
+ let child = next . child ;
923
+ while ( child !== null ) {
924
+ actualDuration += child . actualDuration ;
925
+ child = child . sibling ;
926
+ }
927
+ next . actualDuration = actualDuration ;
928
+ }
929
+ }
930
+
911
931
// If completing this work spawned new work, do that next. We'll come
912
932
// back here again.
913
933
// Since we're restarting, remove anything that is not a host effect
@@ -968,15 +988,14 @@ function performUnitOfWork(workInProgress: Fiber): Fiber | null {
968
988
let next ;
969
989
if ( enableProfilerTimer ) {
970
990
if ( workInProgress . mode & ProfileMode ) {
971
- startBaseRenderTimer ( ) ;
991
+ startProfilerTimer ( workInProgress ) ;
972
992
}
973
993
974
994
next = beginWork ( current , workInProgress , nextRenderExpirationTime ) ;
975
995
976
996
if ( workInProgress . mode & ProfileMode ) {
977
- // Update "base" time if the render wasn't bailed out on.
978
- recordElapsedBaseRenderTimeIfRunning ( workInProgress ) ;
979
- stopBaseRenderTimerIfRunning ( ) ;
997
+ // Record the render duration assuming we didn't bailout (or error).
998
+ stopProfilerTimerIfRunningAndRecordDelta ( workInProgress , true ) ;
980
999
}
981
1000
} else {
982
1001
next = beginWork ( current , workInProgress , nextRenderExpirationTime ) ;
@@ -1017,12 +1036,6 @@ function workLoop(isYieldy) {
1017
1036
while ( nextUnitOfWork !== null && ! shouldYield ( ) ) {
1018
1037
nextUnitOfWork = performUnitOfWork ( nextUnitOfWork ) ;
1019
1038
}
1020
-
1021
- if ( enableProfilerTimer ) {
1022
- // If we didn't finish, pause the "actual" render timer.
1023
- // We'll restart it when we resume work.
1024
- pauseActualRenderTimerIfRunning ( ) ;
1025
- }
1026
1039
}
1027
1040
}
1028
1041
@@ -1068,11 +1081,6 @@ function renderRoot(
1068
1081
try {
1069
1082
workLoop ( isYieldy ) ;
1070
1083
} catch ( thrownValue ) {
1071
- if ( enableProfilerTimer ) {
1072
- // Stop "base" render timer in the event of an error.
1073
- stopBaseRenderTimerIfRunning ( ) ;
1074
- }
1075
-
1076
1084
if ( nextUnitOfWork === null ) {
1077
1085
// This is a fatal error.
1078
1086
didFatal = true ;
@@ -1139,10 +1147,6 @@ function renderRoot(
1139
1147
// There was a fatal error.
1140
1148
if ( __DEV__ ) {
1141
1149
resetStackAfterFatalErrorInDev ( ) ;
1142
-
1143
- // Reset the DEV fiber stack in case we're profiling roots.
1144
- // (We do this for profiling bulds when DevTools is detected.)
1145
- resetActualRenderTimerStackAfterFatalErrorInDev ( ) ;
1146
1150
}
1147
1151
// `nextRoot` points to the in-progress root. A non-null value indicates
1148
1152
// that we're in the middle of an async render. Set it to null to indicate
@@ -1871,10 +1875,6 @@ function performWork(minExpirationTime: ExpirationTime, dl: Deadline | null) {
1871
1875
// the deadline.
1872
1876
findHighestPriorityRoot ( ) ;
1873
1877
1874
- if ( enableProfilerTimer ) {
1875
- resumeActualRenderTimerIfPaused ( minExpirationTime === Sync ) ;
1876
- }
1877
-
1878
1878
if ( deadline !== null ) {
1879
1879
recomputeCurrentRendererTime ( ) ;
1880
1880
currentSchedulerTime = currentRendererTime ;
@@ -1947,7 +1947,6 @@ function flushRoot(root: FiberRoot, expirationTime: ExpirationTime) {
1947
1947
performWorkOnRoot ( root , expirationTime , true ) ;
1948
1948
// Flush any sync work that was scheduled by lifecycles
1949
1949
performSyncWork ( ) ;
1950
- pauseActualRenderTimerIfRunning ( ) ;
1951
1950
}
1952
1951
1953
1952
function finishRendering ( ) {
@@ -2049,12 +2048,6 @@ function performWorkOnRoot(
2049
2048
// There's no time left. Mark this root as complete. We'll come
2050
2049
// back and commit it later.
2051
2050
root . finishedWork = finishedWork ;
2052
-
2053
- if ( enableProfilerTimer ) {
2054
- // If we didn't finish, pause the "actual" render timer.
2055
- // We'll restart it when we resume work.
2056
- pauseActualRenderTimerIfRunning ( ) ;
2057
- }
2058
2051
}
2059
2052
}
2060
2053
}
0 commit comments