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 08:55:26 -08:00 коммит произвёл Facebook Github Bot
Родитель 95c414cfbf
Коммит 70447775f7
6 изменённых файлов: 53 добавлений и 48 удалений

Просмотреть файл

@ -19,31 +19,34 @@
using namespace facebook::react;
class SchedulerDelegateProxy: public SchedulerDelegate {
public:
SchedulerDelegateProxy(void *scheduler):
scheduler_(scheduler) {}
class SchedulerDelegateProxy : public SchedulerDelegate {
public:
SchedulerDelegateProxy(void *scheduler) : scheduler_(scheduler) {}
void schedulerDidFinishTransaction(Tag rootTag, const ShadowViewMutationList &mutations, const long commitStartTime, const long layoutTime) override {
void schedulerDidFinishTransaction(
Tag rootTag,
const ShadowViewMutationList &mutations,
const long commitStartTime,
const long layoutTime) override
{
RCTScheduler *scheduler = (__bridge RCTScheduler *)scheduler_;
[scheduler.delegate schedulerDidFinishTransaction:mutations rootTag:rootTag];
}
void schedulerDidRequestPreliminaryViewAllocation(
SurfaceId surfaceId,
ComponentName componentName,
bool isLayoutable,
ComponentHandle componentHandle) override
const ShadowView &shadowView) override
{
if (!isLayoutable) {
return;
}
RCTScheduler *scheduler = (__bridge RCTScheduler *)scheduler_;
[scheduler.delegate schedulerOptimisticallyCreateComponentViewWithComponentHandle:componentHandle];
[scheduler.delegate schedulerOptimisticallyCreateComponentViewWithComponentHandle:shadowView.componentHandle];
}
private:
private:
void *scheduler_;
};
@ -56,7 +59,8 @@ private:
{
if (self = [super init]) {
_delegateProxy = std::make_shared<SchedulerDelegateProxy>((__bridge void *)self);
_scheduler = std::make_shared<Scheduler>(std::static_pointer_cast<ContextContainer>(contextContainer), getDefaultComponentRegistryFactory());
_scheduler = std::make_shared<Scheduler>(
std::static_pointer_cast<ContextContainer>(contextContainer), getDefaultComponentRegistryFactory());
_scheduler->setDelegate(_delegateProxy.get());
}
@ -77,17 +81,9 @@ private:
SystraceSection s("-[RCTScheduler startSurfaceWithSurfaceId:...]");
auto props = convertIdToFollyDynamic(initialProps);
_scheduler->startSurface(
surfaceId,
RCTStringFromNSString(moduleName),
props,
layoutConstraints,
layoutContext);
_scheduler->startSurface(surfaceId, RCTStringFromNSString(moduleName), props, layoutConstraints, layoutContext);
_scheduler->renderTemplateToSurface(
surfaceId,
props.getDefault("navigationConfig")
.getDefault("initialUITemplate", "")
.getString());
surfaceId, props.getDefault("navigationConfig").getDefault("initialUITemplate", "").getString());
}
- (void)stopSurfaceWithSurfaceId:(SurfaceId)surfaceId

Просмотреть файл

@ -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() {

Просмотреть файл

@ -261,9 +261,7 @@ void Scheduler::uiManagerDidCreateShadowNode(
auto shadowView = ShadowView(*shadowNode);
delegate_->schedulerDidRequestPreliminaryViewAllocation(
shadowNode->getRootTag(),
isLayoutable,
shadowView);
shadowNode->getRootTag(), isLayoutable, shadowView);
}
}