4
4
#import < QuartzCore/QuartzCore.h>
5
5
#import < React/RCTRootView.h>
6
6
#import < React/RCTPerformanceLogger.h>
7
+ #import < cxxreact/ReactMarker.h>
8
+
7
9
#import " RNPerformanceUtils.h"
8
10
9
11
#ifdef RCT_NEW_ARCH_ENABLED
13
15
static int64_t sNativeLaunchStart ;
14
16
static int64_t sNativeLaunchEnd ;
15
17
18
+ using namespace facebook ::react;
19
+
16
20
@implementation RNPerformanceManager
17
21
{
18
22
bool hasListeners;
19
23
bool didEmit;
24
+ int64_t contentAppeared;
20
25
}
21
26
22
27
RCT_EXPORT_MODULE ();
@@ -30,12 +35,22 @@ + (void) initialize
30
35
sNativeLaunchStart = sNativeLaunchEnd - (tp.tv_sec * 1e3 + tp.tv_nsec / 1e6 );
31
36
}
32
37
38
+ - (instancetype )init
39
+ {
40
+ if (self = [super init ]) {
41
+ hasListeners = NO ;
42
+ didEmit = NO ;
43
+ contentAppeared = -1 ;
44
+ }
45
+ return self;
46
+ }
47
+
33
48
- (void )setBridge : (RCTBridge *)bridge
34
49
{
35
50
[super setBridge: bridge];
36
51
[RNPerformance.sharedInstance clearEphemeralEntries ];
37
52
[[NSNotificationCenter defaultCenter ] addObserver: self
38
- selector: @selector (emitIfReady )
53
+ selector: @selector (contentAppeared )
39
54
name: RCTContentDidAppearNotification
40
55
object: nil ];
41
56
[[NSNotificationCenter defaultCenter ] addObserver: self
@@ -48,9 +63,20 @@ - (void)setBridge:(RCTBridge *)bridge
48
63
object: nil ];
49
64
}
50
65
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
+
51
77
- (void )emitIfReady
52
78
{
53
- if (!didEmit && hasListeners && [self .bridge.performanceLogger valueForTag: RCTPLTTI] != 0 && [ self .bridge.performanceLogger valueForTag: RCTPLScriptExecution] != 0 ) {
79
+ if (!didEmit && hasListeners && [self isReady ] ) {
54
80
[self emitEntries ];
55
81
}
56
82
}
@@ -67,10 +93,13 @@ - (void)emitEntries
67
93
didEmit = YES ;
68
94
[self emitMarkNamed: @" nativeLaunchStart" withStartTime: sNativeLaunchStart ];
69
95
[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];
74
103
[self emitMetricNamed: @" bundleSize" withValue: @([self .bridge.performanceLogger valueForTag: RCTPLBundleSize]) withStartTime: RNPerformanceGetTimestamp () withDetail: @{ @" unit" : @" byte" }];
75
104
[[RNPerformance.sharedInstance getEntries ]
76
105
enumerateObjectsUsingBlock: ^(RNPerformanceEntry * _Nonnull entry, NSUInteger idx, BOOL * _Nonnull stop) {
@@ -106,7 +135,7 @@ - (void)invalidate
106
135
- (void )startObserving
107
136
{
108
137
hasListeners = YES ;
109
- if (didEmit != YES && [self .bridge.performanceLogger valueForTag: RCTPLTTI] != 0 && [ self .bridge.performanceLogger valueForTag: RCTPLScriptExecution] != 0 ) {
138
+ if (didEmit != YES && [self isReady ] ) {
110
139
[self emitEntries ];
111
140
}
112
141
}
@@ -116,20 +145,12 @@ -(void)stopObserving
116
145
hasListeners = NO ;
117
146
}
118
147
119
- - (void )emitTag : (RCTPLTag) tag withNamePrefix : ( NSString *) namePrefix
148
+ - (void )emitMarkNamed : ( NSString *) name withMediaTime : ( int64_t ) mediaTime
120
149
{
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);
125
152
return ;
126
153
}
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
- {
133
154
[self emitMarkNamed: name withStartTime: mediaTime + RNPerformanceGetTimestamp () - (CACurrentMediaTime () * 1000 )];
134
155
}
135
156
0 commit comments