Update Props during pre-allocation avoiding re-updating the same props during mounting

Summary:
Update Props during pre-allocation avoiding re-updating the same props during mounting

MobileLab test showed an improvement of:
MARKETPLACE_YOU_TTI_SUCCESS: -3.34% = 58ms

Reviewed By: shergin

Differential Revision: D14252170

fbshipit-source-id: 1f4e9ad5dcecbc06651fa065135ffeed4892d984
This commit is contained in:
David Vacca
2019-03-03 09:00:48 -08:00
committed by Facebook Github Bot
parent 95c414cfbf
commit 70447775f7
6 changed files with 53 additions and 48 deletions
@@ -21,7 +21,6 @@ import android.support.annotation.UiThread;
import android.util.Log;
import android.view.View;
import com.facebook.common.logging.FLog;
import com.facebook.infer.annotation.Assertions;
import com.facebook.infer.annotation.ThreadConfined;
import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.react.bridge.LifecycleEventListener;
@@ -73,6 +72,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
private static final Map<String, String> sComponentNames = new HashMap<>();
private static final int FRAME_TIME_MS = 16;
private static final int MAX_TIME_IN_FRAME_FOR_NON_BATCHED_OPERATIONS_MS = 8;
private static final int PRE_MOUNT_ITEMS_INITIAL_SIZE_ARRAY = 250;
static {
FabricSoLoader.staticInit();
@@ -105,7 +105,8 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
private List<MountItem> mMountItems = new ArrayList<>();
@GuardedBy("mPreMountItemsLock")
private ArrayDeque<MountItem> mPreMountItems = new ArrayDeque<>();
private ArrayDeque<MountItem> mPreMountItems = new ArrayDeque<>(
PRE_MOUNT_ITEMS_INITIAL_SIZE_ARRAY);
@ThreadConfined(UI)
private final DispatchUIFrameCallback mDispatchUIFrameCallback;
@@ -165,7 +166,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
@DoNotStrip
@SuppressWarnings("unused")
private MountItem createMountItem(
String componentName, int reactRootTag, int reactTag, boolean isVirtual) {
String componentName, int reactRootTag, int reactTag, boolean isVirtual, ReadableMap props) {
String component = sComponentNames.get(componentName);
if (component == null) {
throw new IllegalArgumentException("Unable to find component with name " + componentName);
@@ -174,7 +175,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
if (reactContext == null) {
throw new IllegalArgumentException("Unable to find ReactContext for root: " + reactRootTag);
}
return new CreateMountItem(reactContext, component, reactTag, isVirtual);
return new CreateMountItem(reactContext, component, reactTag, isVirtual, props);
}
@Override
@@ -197,11 +198,10 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
// There is no reason to allocate views ahead of time on the main thread.
return;
}
ThemedReactContext context = mReactContextForRootTag.get(rootTag);
String component = sComponentNames.get(componentName);
synchronized (mPreMountItemsLock) {
ThemedReactContext context =
Assertions.assertNotNull(mReactContextForRootTag.get(rootTag));
String component = sComponentNames.get(componentName);
Assertions.assertNotNull(component);
mPreMountItems.add(new PreAllocateViewMountItem(context, rootTag, reactTag, component, props));
}
}
@@ -315,6 +315,9 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
mRunStartTime = SystemClock.uptimeMillis();
List<MountItem> mountItemsToDispatch;
synchronized (mMountItemsLock) {
if (mMountItems.isEmpty()) {
return;
}
mountItemsToDispatch = mMountItems;
mMountItems = new ArrayList<>();
}
@@ -173,7 +173,7 @@ local_ref<JMountItem::javaobject> createCreateMountItem(
const Tag rootTag) {
static auto createJavaInstruction =
jni::findClassStatic(UIManagerJavaDescriptor)
->getMethod<alias_ref<JMountItem>(jstring, jint, jint, jboolean)>(
->getMethod<alias_ref<JMountItem>(jstring, jint, jint, jboolean, ReadableMap::javaobject)>(
"createMountItem");
auto newChildShadowView = mutation.newChildShadowView;
@@ -183,12 +183,16 @@ local_ref<JMountItem::javaobject> createCreateMountItem(
jboolean isVirtual = newChildShadowView.layoutMetrics == EmptyLayoutMetrics;
local_ref<ReadableMap::javaobject> props = isVirtual ? nullptr :
castReadableMap(ReadableNativeMap::newObjectCxxArgs(newChildShadowView.props->rawProps));
return createJavaInstruction(
javaUIManager,
componentName.get(),
rootTag,
newChildShadowView.tag,
isVirtual);
isVirtual,
props != nullptr ? props.get() : nullptr);
}
local_ref<JMountItem::javaobject> createUpdateEventEmitterMountItem(
@@ -402,7 +406,7 @@ void Binding::schedulerDidFinishTransaction(
mountItems[position++] =
createInsertMountItem(javaUIManager_, mutation);
if (mutation.newChildShadowView.props->revision != 0) {
if (mutation.newChildShadowView.props->revision > 1) {
mountItems[position++] =
createUpdatePropsMountItem(javaUIManager_, mutation);
}
@@ -465,20 +469,16 @@ void Binding::schedulerDidRequestPreliminaryViewAllocation(
const SurfaceId surfaceId,
bool isLayoutable,
const ShadowView &shadowView) {
if (isLayoutable) {
static auto preallocateView =
jni::findClassStatic(UIManagerJavaDescriptor)
->getMethod<void(jint, jint, jstring, ReadableMap::javaobject)>("preallocateView");
if (shadowView.props->rawProps.isNull()) {
local_ref<ReadableMap::javaobject> readableMap =
castReadableMap(ReadableNativeMap::newObjectCxxArgs(shadowView.props->rawProps));
preallocateView(
javaUIManager_, surfaceId, shadowView.tag, make_jstring(shadowView.componentName).get(), readableMap.get());
} else {
preallocateView(
javaUIManager_, surfaceId, shadowView.tag, make_jstring(shadowView.componentName).get(), nullptr);
}
local_ref<ReadableMap::javaobject> readableMap =
castReadableMap(ReadableNativeMap::newObjectCxxArgs(shadowView.props->rawProps));
preallocateView(
javaUIManager_, surfaceId, shadowView.tag, make_jstring(shadowView.componentName).get(), readableMap.get());
}
}
@@ -168,8 +168,8 @@ public class MountingManager {
ThemedReactContext themedReactContext,
String componentName,
int reactTag,
boolean isVirtual) {
UiThreadUtil.assertOnUiThread();
View view = null;
ViewManager viewManager = null;
@@ -280,10 +280,11 @@ public class MountingManager {
String componentName,
int reactTag,
ReadableMap props) {
if (mTagToViewState.get(reactTag) != null) return;
createView(reactContext, componentName, reactTag, false);
if (props != null) {
updateProps(reactTag, props);
}
updateProps(reactTag, props);
}
@UiThread
@@ -6,6 +6,7 @@
*/
package com.facebook.react.fabric.mounting.mountitems;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.fabric.mounting.MountingManager;
import com.facebook.react.uimanager.ThemedReactContext;
@@ -15,21 +16,27 @@ public class CreateMountItem implements MountItem {
private final int mReactTag;
private final ThemedReactContext mThemedReactContext;
private final boolean mIsVirtual;
private final ReadableMap mProps;
public CreateMountItem(
ThemedReactContext themedReactContext,
String componentName,
int reactTag,
boolean isVirtual) {
boolean isVirtual,
ReadableMap props) {
mReactTag = reactTag;
mThemedReactContext = themedReactContext;
mComponentName = componentName;
mIsVirtual = isVirtual;
mProps = props;
}
@Override
public void execute(MountingManager mountingManager) {
mountingManager.createView(mThemedReactContext, mComponentName, mReactTag, mIsVirtual);
if (mProps != null && !mIsVirtual) {
mountingManager.updateProps(mReactTag, mProps);
}
}
public String getComponentName() {