Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Navigation perf profiling #1658

Draft
wants to merge 1 commit into
base: development
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Example/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,12 @@ import com.android.build.OutputFile
*/

project.ext.react = [
cliPath: "../node_modules/react-native/cli.js", // path is relative to `process.cwd`
composeSourceMapsPath: "../node_modules/react-native/scripts/compose-source-maps.js", // path is relative to `process.cwd`
cliPath: "../../../node_modules/react-native/cli.js", // path is relative to `process.cwd`
composeSourceMapsPath: "../../../node_modules/react-native/scripts/compose-source-maps.js", // path is relative to `process.cwd`
enableHermes: true, // clean and rebuild if changing
entryFile: "index.js", // path is relative to `process.cwd`
hermesCommand: "../../../node_modules/hermes-engine/osx-bin/hermesc",
// bundleInDebug: true,
]

project.ext.themes = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import java.util.List;

import com.facebook.react.bridge.JSIModulePackage;
import com.swmansion.reanimated.ReanimatedPackage;

import tonlabs.uikit.keyboard.UIKitKeyboardJSIModulePackage;

public class MainApplication extends Application implements ReactApplication {
Expand All @@ -35,7 +37,11 @@ protected List<ReactPackage> getPackages() {
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());

return packages;
packages = PatchedReanimatedPackage.patchPackages(packages);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be a good idea to apply it in Surf anyway as it completely remove patched UIManager from reanimated that they use for layout animations and it has useless overhead


packages.add(new TracePackage());

return packages;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package tonlabs.uikit;
import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_END;
import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_START;

import com.facebook.react.ReactApplication;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactPackage;
import com.facebook.react.TurboReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactMarker;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.module.model.ReactModuleInfo;
import com.facebook.react.module.model.ReactModuleInfoProvider;
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
import com.facebook.react.uimanager.ReanimatedUIManager;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.systrace.Systrace;
import com.swmansion.reanimated.ReanimatedModule;
import com.swmansion.reanimated.ReanimatedPackage;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class PatchedReanimatedPackage extends TurboReactPackage implements ReactPackage {

static List<ReactPackage> patchPackages(List<ReactPackage> packages) {
int reaPackageIndex = -1;
for (ReactPackage _package : packages) {
if (_package instanceof ReanimatedPackage) {
reaPackageIndex = packages.indexOf(_package);
}
}
if (reaPackageIndex > 0) {
packages.remove(reaPackageIndex);
}

packages.add(new PatchedReanimatedPackage());

return packages;
}

@Override
public NativeModule getModule(String name, ReactApplicationContext reactContext) {
if (name.equals(ReanimatedModule.NAME)) {
return new ReanimatedModule(reactContext);
}
return null;
}

@Override
public ReactModuleInfoProvider getReactModuleInfoProvider() {
Class<? extends NativeModule>[] moduleList =
new Class[] {
ReanimatedModule.class,
};

final Map<String, ReactModuleInfo> reactModuleInfoMap = new HashMap<>();
for (Class<? extends NativeModule> moduleClass : moduleList) {
ReactModule reactModule = moduleClass.getAnnotation(ReactModule.class);

reactModuleInfoMap.put(
reactModule.name(),
new ReactModuleInfo(
reactModule.name(),
moduleClass.getName(),
true,
reactModule.needsEagerInit(),
reactModule.hasConstants(),
reactModule.isCxxModule(),
TurboModule.class.isAssignableFrom(moduleClass)));
}

return new ReactModuleInfoProvider() {
@Override
public Map<String, ReactModuleInfo> getReactModuleInfos() {
return reactModuleInfoMap;
}
};
}

private UIManagerModule createUIManager(final ReactApplicationContext reactContext) {
ReactMarker.logMarker(CREATE_UI_MANAGER_MODULE_START);
Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "createUIManagerModule");
final ReactInstanceManager reactInstanceManager = getReactInstanceManager(reactContext);
int minTimeLeftInFrameForNonBatchedOperationMs = -1;
try {
return new ReanimatedUIManager(
reactContext,
reactInstanceManager.getOrCreateViewManagers(reactContext),
minTimeLeftInFrameForNonBatchedOperationMs);
} finally {
Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
ReactMarker.logMarker(CREATE_UI_MANAGER_MODULE_END);
}
}

/**
* Get the {@link ReactInstanceManager} used by this app. By default, assumes {@link
* ReactApplicationContext#getApplicationContext()} is an instance of {@link ReactApplication} and
* calls {@link ReactApplication#getReactNativeHost().getReactInstanceManager()}. Override this
* method if your application class does not implement {@code ReactApplication} or you simply have
* a different mechanism for storing a {@code ReactInstanceManager}, e.g. as a static field
* somewhere.
*/
public ReactInstanceManager getReactInstanceManager(ReactApplicationContext reactContext) {
return ((ReactApplication) reactContext.getApplicationContext())
.getReactNativeHost()
.getReactInstanceManager();
}
}
11 changes: 11 additions & 0 deletions Example/android/app/src/main/java/tonlabs/uikit/TraceLog.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package tonlabs.uikit;

import android.util.Log;

public class TraceLog {
static final String TAG = "RNSTEST";

public static void log(String payload) {
Log.d(TAG, payload + " : " + System.currentTimeMillis());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package tonlabs.uikit;

import androidx.annotation.Nullable;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.uimanager.NativeViewHierarchyManager;
import com.facebook.react.uimanager.ReactStylesDiffMap;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.TraceUIViewOperationQueue;
import com.facebook.react.uimanager.ViewAtIndex;
import com.facebook.react.uimanager.ViewGroupManager;
import com.facebook.react.uimanager.ViewManagerRegistry;

public class TraceNativeViewHierarchyManager extends NativeViewHierarchyManager {
public TraceUIViewOperationQueue mTraceUIViewOperationQueue;

public TraceNativeViewHierarchyManager(
ViewManagerRegistry viewManagers) {
super(viewManagers);
}

@Override
public synchronized void createView(ThemedReactContext themedContext, int tag, String className, @Nullable ReactStylesDiffMap initialProps) {
TraceLog.log("TraceNativeViewHierarchyManager createView " + className);
if (className.equals("RNSScreen")) {
mTraceUIViewOperationQueue.printableDoFrames = 10;
}

// long t = System.currentTimeMillis();
super.createView(themedContext, tag, className, initialProps);
// TraceLog.log("TraceNativeViewHierarchyManager createView - " + (System.currentTimeMillis() - t) + " " + className);
}

@Override
public synchronized void manageChildren(int tag, @Nullable int[] indicesToRemove, @Nullable ViewAtIndex[] viewsToAdd, @Nullable int[] tagsToDelete) {
final ViewGroupManager viewManager = (ViewGroupManager)this.resolveViewManager(tag);
TraceLog.log("TraceNativeViewHierarchyManager manageChildren " + viewManager.getName() + " (calls addView)");

super.manageChildren(tag, indicesToRemove, viewsToAdd, tagsToDelete);
}

@Override
public synchronized void setChildren(int tag, ReadableArray childrenTags) {
TraceLog.log("TraceNativeViewHierarchyManager setChildren (calls addView)");
super.setChildren(tag, childrenTags);
}
}
49 changes: 49 additions & 0 deletions Example/android/app/src/main/java/tonlabs/uikit/TracePackage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package tonlabs.uikit;

import androidx.annotation.NonNull;

import com.facebook.react.ReactApplication;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.TraceUIManagerModule;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.ViewManager;

import java.util.ArrayList;
import java.util.List;

public class TracePackage implements ReactPackage {

@NonNull
@Override
public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(createUIManager(reactContext));
return modules;
}

@NonNull
@Override
public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) {
List<ViewManager> modules = new ArrayList<>();
return modules;
}

private UIManagerModule createUIManager(final ReactApplicationContext reactContext) {
final ReactInstanceManager reactInstanceManager = getReactInstanceManager(reactContext);
int minTimeLeftInFrameForNonBatchedOperationMs = -1;

return new TraceUIManagerModule(
reactContext,
reactInstanceManager.getOrCreateViewManagers(reactContext),
minTimeLeftInFrameForNonBatchedOperationMs);
}

public ReactInstanceManager getReactInstanceManager(ReactApplicationContext reactContext) {
return ((ReactApplication) reactContext.getApplicationContext())
.getReactNativeHost()
.getReactInstanceManager();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package tonlabs.uikit;

import androidx.annotation.Nullable;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.uimanager.TraceUIViewOperationQueue;
import com.facebook.react.uimanager.UIImplementation;
import com.facebook.react.uimanager.UIViewOperationQueue;
import com.facebook.react.uimanager.ViewManager;
import com.facebook.react.uimanager.ViewManagerRegistry;
import com.facebook.react.uimanager.ViewManagerResolver;
import com.facebook.react.uimanager.events.EventDispatcher;

public class TraceUIImplementation extends UIImplementation {
public TraceUIImplementation(
ReactApplicationContext reactContext,
ViewManagerRegistry viewManagerRegistry,
EventDispatcher eventDispatcher,
int minTimeLeftInFrameForNonBatchedOperationMs) {
super(
reactContext,
viewManagerRegistry,
new TraceUIViewOperationQueue(
reactContext,
new TraceNativeViewHierarchyManager(viewManagerRegistry),
minTimeLeftInFrameForNonBatchedOperationMs),
eventDispatcher);
}

public void createView(int tag, String className, int rootViewTag, ReadableMap props) {
TraceLog.log("TraceUIImplementation createView " + className);
// long t = System.currentTimeMillis();
super.createView(tag, className, rootViewTag, props);
// TraceLog.log("TraceUIManagerModule creationTime - " + (System.currentTimeMillis() - t) + " " + className);
}

public void updateView(final int tag, final String className, final ReadableMap props) {
TraceLog.log("TraceUIImplementation updateView " + className);
long t = System.currentTimeMillis();
super.updateView(tag, className, props);
TraceLog.log("TraceUIManagerModule updateTime - " + (System.currentTimeMillis() - t) + " " + className);
}

public void manageChildren(
int viewTag,
@Nullable ReadableArray moveFrom,
@Nullable ReadableArray moveTo,
@Nullable ReadableArray addChildTags,
@Nullable ReadableArray addAtIndices,
@Nullable ReadableArray removeFrom) {
TraceLog.log("TraceUIImplementation manageChildren1");
super.manageChildren(viewTag, moveFrom, moveTo, addChildTags, addAtIndices, removeFrom);
TraceLog.log("TraceUIImplementation manageChildren2");
}
}
Loading