Dispatch view creation immediately instead of waiting for layout

Summary:All UIManager operations that affect the view hierarchy are executed via the `addUIBlock:` method, which queues them up to be executed after layout has been completed on the shadow queue.

One of the most expensive view operations is view creation, but since this doesn't actually depend on layout, there's no reason to delay it until the shadow operations have finished.

This diff modifies the `createView` method to dispatch view creation directly to the main thread instead of adding it to the UIBlock queue. This seems to result a measurable improvement in TTI.

(Credit to astreet, for implementing the same idea on Android, and thanks to oli for telling me about it!)

Reviewed By: javache

Differential Revision: D3155709

fb-gh-sync-id: 3ad1da9a8fee687aa7e0e023d668192d94dba340
fbshipit-source-id: 3ad1da9a8fee687aa7e0e023d668192d94dba340
This commit is contained in:
Nick Lockwood 2016-04-11 05:05:25 -07:00 committed by Facebook Github Bot 3
parent d66b944727
commit c55ca61396
1 changed files with 10 additions and 3 deletions

View File

@ -897,7 +897,14 @@ RCT_EXPORT_METHOD(createView:(nonnull NSNumber *)reactTag
// the view, but it's the only way that makes sense given our threading model // the view, but it's the only way that makes sense given our threading model
UIColor *backgroundColor = shadowView.backgroundColor; UIColor *backgroundColor = shadowView.backgroundColor;
[self addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry){ // Dispatch view creation directly to the main thread instead of adding to
// UIBlocks array. This way, it doesn't get deferred until after layout.
__weak RCTUIManager *weakManager = self;
dispatch_async(dispatch_get_main_queue(), ^{
RCTUIManager *uiManager = weakManager;
if (!uiManager) {
return;
}
UIView *view = [componentData createViewWithTag:reactTag]; UIView *view = [componentData createViewWithTag:reactTag];
if (view) { if (view) {
[componentData setProps:props forView:view]; // Must be done before bgColor to prevent wrong default [componentData setProps:props forView:view]; // Must be done before bgColor to prevent wrong default
@ -907,13 +914,13 @@ RCT_EXPORT_METHOD(createView:(nonnull NSNumber *)reactTag
if ([view respondsToSelector:@selector(reactBridgeDidFinishTransaction)]) { if ([view respondsToSelector:@selector(reactBridgeDidFinishTransaction)]) {
[uiManager->_bridgeTransactionListeners addObject:view]; [uiManager->_bridgeTransactionListeners addObject:view];
} }
((NSMutableDictionary<NSNumber *, UIView *> *)viewRegistry)[reactTag] = view; uiManager->_viewRegistry[reactTag] = view;
#if RCT_DEV #if RCT_DEV
[view _DEBUG_setReactShadowView:shadowView]; [view _DEBUG_setReactShadowView:shadowView];
#endif #endif
} }
}]; });
} }
RCT_EXPORT_METHOD(updateView:(nonnull NSNumber *)reactTag RCT_EXPORT_METHOD(updateView:(nonnull NSNumber *)reactTag