Optimize pre-allocation of views

Summary: This diff changes the way pre-allocation of views are executed in Fabric. Before this diff the execution of view preallocation was schedulled at the end of the UIThread queue, now the views are pre-allocated in the next "tick"

Reviewed By: sahrens

Differential Revision: D13857614

fbshipit-source-id: 386bf966d3c8a0d5c0bd626119a92810465aecb7
This commit is contained in:
David Vacca
2019-01-30 00:15:25 -08:00
committed by Facebook Github Bot
parent 4c69ccd0fb
commit 16a6e51045
3 changed files with 65 additions and 17 deletions
@@ -29,6 +29,7 @@ import com.facebook.react.fabric.mounting.mountitems.DeleteMountItem;
import com.facebook.react.fabric.mounting.mountitems.DispatchCommandMountItem;
import com.facebook.react.fabric.mounting.mountitems.InsertMountItem;
import com.facebook.react.fabric.mounting.mountitems.MountItem;
import com.facebook.react.fabric.mounting.mountitems.PreAllocateViewMountItem;
import com.facebook.react.fabric.mounting.mountitems.RemoveMountItem;
import com.facebook.react.fabric.mounting.mountitems.UpdateEventEmitterMountItem;
import com.facebook.react.fabric.mounting.mountitems.UpdateLayoutMountItem;
@@ -49,6 +50,7 @@ import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.modules.core.ReactChoreographer;
import com.facebook.react.uimanager.IllegalViewOperationException;
import com.facebook.react.uimanager.ReactRootViewTagGenerator;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ViewManagerPropertyUpdater;
@@ -94,10 +96,14 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
new ConcurrentHashMap<>();
private final EventBeatManager mEventBeatManager;
private final Object mMountItemsLock = new Object();
private final Object mPreMountItemsLock = new Object();
@GuardedBy("mMountItemsLock")
private List<MountItem> mMountItems = new ArrayList<>();
@GuardedBy("mPreMountItemsLock")
private List<MountItem> mPreMountItems = new ArrayList<>();
@ThreadConfined(UI)
private final DispatchUIFrameCallback mDispatchUIFrameCallback;
@@ -177,17 +183,13 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
@DoNotStrip
private void preallocateView(final int rootTag, final String componentName) {
UiThreadUtil.runOnUiThread(
new GuardedRunnable(mReactApplicationContext) {
@Override
public void runGuarded() {
ThemedReactContext context =
Assertions.assertNotNull(mReactContextForRootTag.get(rootTag));
String component = sComponentNames.get(componentName);
Assertions.assertNotNull(component);
mMountingManager.preallocateView(context, component);
}
});
synchronized (mPreMountItemsLock) {
ThemedReactContext context =
Assertions.assertNotNull(mReactContextForRootTag.get(rootTag));
String component = sComponentNames.get(componentName);
Assertions.assertNotNull(component);
mPreMountItems.add(new PreAllocateViewMountItem(context, rootTag, component));
}
}
@DoNotStrip
@@ -286,25 +288,35 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
}
try {
List<MountItem> preMountItemsToDispatch;
synchronized (mPreMountItemsLock) {
preMountItemsToDispatch = mPreMountItems;
mPreMountItems = new ArrayList<>();
}
List<MountItem> mountItemsToDispatch;
synchronized (mMountItemsLock) {
if (mMountItems.isEmpty()) {
return;
}
mountItemsToDispatch = mMountItems;
mMountItems = new ArrayList<>();
}
Systrace.beginSection(
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE,
"FabricUIManager::premountViews (" + preMountItemsToDispatch.size() + " batches)");
for (MountItem mountItem : preMountItemsToDispatch) {
mountItem.execute(mMountingManager);
}
Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
Systrace.beginSection(
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE,
"FabricUIManager::mountViews (" + mountItemsToDispatch.size() + " batches)");
for (MountItem mountItem : mountItemsToDispatch) {
mountItem.execute(mMountingManager);
}
Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
} catch (Exception ex) {
FLog.i(ReactConstants.TAG, "Exception thrown when executing UIFrameGuarded", ex);
FLog.e(ReactConstants.TAG, "Exception thrown when executing UIFrameGuarded", ex);
mIsMountingEnabled = false;
throw ex;
}
@@ -6,8 +6,8 @@
*/
package com.facebook.react.fabric.mounting.mountitems;
import com.facebook.react.fabric.mounting.MountingManager;
import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.react.fabric.mounting.MountingManager;
import com.facebook.systrace.Systrace;
/**
@@ -0,0 +1,36 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.fabric.mounting.mountitems;
import com.facebook.react.fabric.mounting.MountingManager;
import com.facebook.react.uimanager.ThemedReactContext;
/**
* {@link MountItem} that is used to pre-allocate views for JS components.
*/
public class PreAllocateViewMountItem implements MountItem {
private final String mComponent;
private final int mRootTag;
private final ThemedReactContext mContext;
public PreAllocateViewMountItem(ThemedReactContext context, int rootTag, String component){
mContext = context;
mComponent = component;
mRootTag = rootTag;
}
@Override
public void execute(MountingManager mountingManager) {
mountingManager.preallocateView(mContext, mComponent);
}
@Override
public String toString() {
return "[" + mRootTag + "] - Preallocate " + mComponent;
}
}