[ReactNative] Track bridge events' flow

Summary:
@public

Use trace-viewer's flow events to link the bridge calls

Test Plan: {F22498582}
This commit is contained in:
Tadeu Zagallo 2015-06-02 06:13:41 -07:00
parent 0aa7f3f8d5
commit 2dfa3b34a1
4 changed files with 92 additions and 20 deletions

View File

@ -1339,8 +1339,11 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin
* AnyThread
*/
RCTProfileBeginFlowEvent();
__weak RCTBatchedBridge *weakSelf = self;
[_javaScriptExecutor executeBlockOnJavaScriptQueue:^{
RCTProfileEndFlowEvent();
RCTProfileBeginEvent();
RCTBatchedBridge *strongSelf = weakSelf;
@ -1348,13 +1351,17 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin
return;
}
id call = @{
@"module": module,
@"method": method,
@"args": args,
@"context": context ?: @0,
};
RCT_IF_DEV(NSNumber *callID = _RCTProfileBeginFlowEvent();)
id call = @{
@"js_args": @{
@"module": module,
@"method": method,
@"args": args,
},
@"context": context ?: @0,
RCT_IF_DEV(@"call_id": callID,)
};
if ([method isEqualToString:@"invokeCallbackAndReturnFlushedQueue"]) {
strongSelf->_scheduledCallbacks[args[0]] = call;
} else {
@ -1490,8 +1497,10 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin
return NO;
}
RCTProfileBeginFlowEvent();
__weak RCTBatchedBridge *weakSelf = self;
[self dispatchBlock:^{
RCTProfileEndFlowEvent();
RCTProfileBeginEvent();
RCTBatchedBridge *strongSelf = weakSelf;
@ -1526,30 +1535,41 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(NSString *)module method:(NSStrin
{
RCTAssertJSThread();
RCTProfileImmediateEvent(@"JS Thread Tick", displayLink.timestamp, @"g");
RCTProfileBeginEvent();
RCTFrameUpdate *frameUpdate = [[RCTFrameUpdate alloc] initWithDisplayLink:displayLink];
for (id<RCTFrameUpdateObserver> observer in _frameUpdateObservers) {
if (![observer respondsToSelector:@selector(isPaused)] || ![observer isPaused]) {
[self dispatchBlock:^{
[observer didUpdateFrame:frameUpdate];
} forModule:RCTModuleIDsByName[RCTBridgeModuleNameForClass([observer class])]];
}
}
NSArray *calls = [_scheduledCallbacks.allObjects arrayByAddingObjectsFromArray:_scheduledCalls];
NSNumber *currentExecutorID = RCTGetExecutorID(_javaScriptExecutor);
calls = [calls filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(NSDictionary *call, NSDictionary *bindings) {
return [call[@"context"] isEqualToNumber:currentExecutorID];
}]];
RCT_IF_DEV(
RCTProfileImmediateEvent(@"JS Thread Tick", displayLink.timestamp, @"g");
for (NSDictionary *call in calls) {
_RCTProfileEndFlowEvent(call[@"call_id"]);
}
)
RCTProfileBeginEvent();
RCTFrameUpdate *frameUpdate = [[RCTFrameUpdate alloc] initWithDisplayLink:displayLink];
for (id<RCTFrameUpdateObserver> observer in _frameUpdateObservers) {
if (![observer respondsToSelector:@selector(isPaused)] || ![observer isPaused]) {
RCT_IF_DEV(NSString *name = [NSString stringWithFormat:@"[%@ didUpdateFrame:%f]", observer, displayLink.timestamp];)
RCTProfileBeginFlowEvent();
[self dispatchBlock:^{
RCTProfileEndFlowEvent();
RCTProfileBeginEvent();
[observer didUpdateFrame:frameUpdate];
RCTProfileEndEvent(name, @"objc_call,fps", nil);
} forModule:RCTModuleIDsByName[RCTBridgeModuleNameForClass([observer class])]];
}
}
if (calls.count > 0) {
_scheduledCalls = [[NSMutableArray alloc] init];
_scheduledCallbacks = [[RCTSparseArray alloc] init];
[self _actuallyInvokeAndProcessModule:@"BatchedBridge"
method:@"processBatch"
arguments:@[calls]
arguments:@[[calls valueForKey:@"js_args"]]
context:RCTGetExecutorID(_javaScriptExecutor)];
}

View File

@ -42,6 +42,12 @@
#endif
#endif
#if RCT_DEV
#define RCT_IF_DEV(...) __VA_ARGS__
#else
#define RCT_IF_DEV(...)
#endif
/**
* By default, only raise an NSAssertion in debug mode
* (custom assert functions will still be called).

View File

@ -22,6 +22,18 @@
#if RCT_DEV
#define RCTProfileBeginFlowEvent() \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wshadow\"") \
NSNumber *__rct_profile_flow_id = _RCTProfileBeginFlowEvent(); \
_Pragma("clang diagnostic pop")
#define RCTProfileEndFlowEvent() \
_RCTProfileEndFlowEvent(__rct_profile_flow_id)
RCT_EXTERN NSNumber *_RCTProfileBeginFlowEvent(void);
RCT_EXTERN void _RCTProfileEndFlowEvent(NSNumber *);
/**
* Returns YES if the profiling information is currently being collected
*/
@ -88,6 +100,12 @@ RCT_EXTERN void RCTProfileImmediateEvent(NSString *, NSTimeInterval , NSString *
#else
#define RCTProfileBeginFlowEvent()
#define _RCTProfileBeginFlowEvent() @0
#define RCTProfileEndFlowEvent()
#define _RCTProfileEndFlowEvent()
#define RCTProfileIsProfiling(...) NO
#define RCTProfileInit(...)
#define RCTProfileEnd(...) @""

View File

@ -171,4 +171,32 @@ void RCTProfileImmediateEvent(NSString *name, NSTimeInterval timestamp, NSString
);
}
NSNumber *_RCTProfileBeginFlowEvent(void)
{
static NSUInteger flowID = 0;
CHECK(@0);
RCTProfileAddEvent(RCTProfileTraceEvents,
@"name": @"flow",
@"id": @(++flowID),
@"cat": @"flow",
@"ph": @"s",
@"ts": RCTProfileTimestamp(CACurrentMediaTime()),
);
return @(flowID);
}
void _RCTProfileEndFlowEvent(NSNumber *flowID)
{
CHECK();
RCTProfileAddEvent(RCTProfileTraceEvents,
@"name": @"flow",
@"id": flowID,
@"cat": @"flow",
@"ph": @"f",
@"ts": RCTProfileTimestamp(CACurrentMediaTime()),
);
}
#endif