44#import < QuartzCore/QuartzCore.h>
55#import < React/RCTRootView.h>
66#import < React/RCTPerformanceLogger.h>
7+ #import < cxxreact/ReactMarker.h>
8+
79#import " RNPerformanceUtils.h"
810
911#ifdef RCT_NEW_ARCH_ENABLED
1315static int64_t sNativeLaunchStart ;
1416static int64_t sNativeLaunchEnd ;
1517
18+ using namespace facebook ::react;
19+
1620@implementation RNPerformanceManager
1721{
1822 bool hasListeners;
1923 bool didEmit;
24+ int64_t contentAppeared;
2025}
2126
2227RCT_EXPORT_MODULE ();
@@ -30,12 +35,22 @@ + (void) initialize
3035 sNativeLaunchStart = sNativeLaunchEnd - (tp.tv_sec * 1e3 + tp.tv_nsec / 1e6 );
3136}
3237
38+ - (instancetype )init
39+ {
40+ if (self = [super init ]) {
41+ hasListeners = NO ;
42+ didEmit = NO ;
43+ contentAppeared = -1 ;
44+ }
45+ return self;
46+ }
47+
3348- (void )setBridge : (RCTBridge *)bridge
3449{
3550 [super setBridge: bridge];
3651 [RNPerformance.sharedInstance clearEphemeralEntries ];
3752 [[NSNotificationCenter defaultCenter ] addObserver: self
38- selector: @selector (emitIfReady )
53+ selector: @selector (contentAppeared )
3954 name: RCTContentDidAppearNotification
4055 object: nil ];
4156 [[NSNotificationCenter defaultCenter ] addObserver: self
@@ -48,9 +63,20 @@ - (void)setBridge:(RCTBridge *)bridge
4863 object: nil ];
4964}
5065
66+ - (BOOL )isReady
67+ {
68+ return contentAppeared != -1 && !std::isnan (ReactMarker::StartupLogger::getInstance ().getRunJSBundleEndTime ());
69+ }
70+
71+ - (void ) contentAppeared
72+ {
73+ contentAppeared = RNPerformanceGetTimestamp ();
74+ [self emitIfReady ];
75+ }
76+
5177- (void )emitIfReady
5278{
53- if (!didEmit && hasListeners && [self .bridge.performanceLogger valueForTag: RCTPLTTI] != 0 && [ self .bridge.performanceLogger valueForTag: RCTPLScriptExecution] != 0 ) {
79+ if (!didEmit && hasListeners && [self isReady ] ) {
5480 [self emitEntries ];
5581 }
5682}
@@ -67,10 +93,13 @@ - (void)emitEntries
6793 didEmit = YES ;
6894 [self emitMarkNamed: @" nativeLaunchStart" withStartTime: sNativeLaunchStart ];
6995 [self emitMarkNamed: @" nativeLaunchEnd" withStartTime: sNativeLaunchEnd ];
70- [self emitTag: RCTPLScriptDownload withNamePrefix: @" download" ];
71- [self emitTag: RCTPLScriptExecution withNamePrefix: @" runJsBundle" ];
72- [self emitTag: RCTPLBridgeStartup withNamePrefix: @" bridgeSetup" ];
73- [self emitMarkNamed: @" contentAppeared" withMediaTime: [self .bridge.performanceLogger valueForTag: RCTPLTTI]];
96+ [self emitMarkNamed: @" runJsBundleStart" withMediaTime:ReactMarker: :StartupLogger: :getInstance ().getRunJSBundleStartTime ()];
97+ [self emitMarkNamed: @" runJsBundleEnd" withMediaTime:ReactMarker: :StartupLogger: :getInstance ().getRunJSBundleEndTime ()];
98+ [self emitMarkNamed: @" appStartupStart" withMediaTime:ReactMarker: :StartupLogger: :getInstance ().getAppStartupStartTime ()];
99+ [self emitMarkNamed: @" appStartupEnd" withMediaTime:ReactMarker: :StartupLogger: :getInstance ().getAppStartupEndTime ()];
100+ [self emitMarkNamed: @" initReactRuntimeStart" withMediaTime:ReactMarker: :StartupLogger: :getInstance ().getInitReactRuntimeStartTime ()];
101+ [self emitMarkNamed: @" initReactRuntimeEnd" withMediaTime:ReactMarker: :StartupLogger: :getInstance ().getInitReactRuntimeEndTime ()];
102+ [self emitMarkNamed: @" contentAppeared" withStartTime: contentAppeared];
74103 [self emitMetricNamed: @" bundleSize" withValue: @([self .bridge.performanceLogger valueForTag: RCTPLBundleSize]) withStartTime: RNPerformanceGetTimestamp () withDetail: @{ @" unit" : @" byte" }];
75104 [[RNPerformance.sharedInstance getEntries ]
76105 enumerateObjectsUsingBlock: ^(RNPerformanceEntry * _Nonnull entry, NSUInteger idx, BOOL * _Nonnull stop) {
@@ -106,7 +135,7 @@ - (void)invalidate
106135- (void )startObserving
107136{
108137 hasListeners = YES ;
109- if (didEmit != YES && [self .bridge.performanceLogger valueForTag: RCTPLTTI] != 0 && [ self .bridge.performanceLogger valueForTag: RCTPLScriptExecution] != 0 ) {
138+ if (didEmit != YES && [self isReady ] ) {
110139 [self emitEntries ];
111140 }
112141}
@@ -116,20 +145,12 @@ -(void)stopObserving
116145 hasListeners = NO ;
117146}
118147
119- - (void )emitTag : (RCTPLTag) tag withNamePrefix : ( NSString *) namePrefix
148+ - (void )emitMarkNamed : ( NSString *) name withMediaTime : ( int64_t ) mediaTime
120149{
121- int64_t duration = [self .bridge.performanceLogger durationForTag: tag];
122- int64_t end = [self .bridge.performanceLogger valueForTag: tag];
123- if (duration == 0 || end == 0 ) {
124- NSLog (@" Ignoring marks prefixed %@ (%lu ) as data is unavailable (duration: %lld , end: %lld )" , namePrefix, (unsigned long )tag, duration, end);
150+ if (mediaTime == 0 ) {
151+ NSLog (@" Ignoring mark named %@ as timestamp is not set" , name);
125152 return ;
126153 }
127- [self emitMarkNamed: [namePrefix stringByAppendingString: @" Start" ] withMediaTime: end-duration];
128- [self emitMarkNamed: [namePrefix stringByAppendingString: @" End" ] withMediaTime: end];
129- }
130-
131- - (void )emitMarkNamed : (NSString *)name withMediaTime : (int64_t )mediaTime
132- {
133154 [self emitMarkNamed: name withStartTime: mediaTime + RNPerformanceGetTimestamp () - (CACurrentMediaTime () * 1000 )];
134155}
135156
0 commit comments