From 16f76d4407a0274cd62524c6b900b2e1eaf30b45 Mon Sep 17 00:00:00 2001 From: Scott Buckfelder Date: Tue, 30 Aug 2016 14:15:48 -0700 Subject: [PATCH] SKETCH Add performance tracking for rendering Differential Revision: D3709400 fbshipit-source-id: a006b60feb3fc5cb55cc2e6f08275fcc8de1d3e1 --- .../react/bridge/PerformanceCounter.java | 15 +++++++++++++++ .../com/facebook/react/bridge/ReactContext.java | 16 ++++++++++++++++ .../react/uimanager/UIImplementation.java | 14 ++++++++++++++ .../react/uimanager/UIManagerModule.java | 11 ++++++++++- 4 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 ReactAndroid/src/main/java/com/facebook/react/bridge/PerformanceCounter.java diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/PerformanceCounter.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/PerformanceCounter.java new file mode 100644 index 00000000000000..c956810e4c9e3e --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/PerformanceCounter.java @@ -0,0 +1,15 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ +package com.facebook.react.bridge; + +import java.util.Map; + +public interface PerformanceCounter { + public Map getPerformanceCounters(); +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java index 8a86668837aeda..9bef44bc5129b0 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java @@ -13,6 +13,8 @@ import java.lang.ref.WeakReference; import java.util.concurrent.CopyOnWriteArraySet; +import java.util.HashMap; +import java.util.Map; import android.app.Activity; import android.content.Context; @@ -143,6 +145,20 @@ public void removeLifecycleEventListener(LifecycleEventListener listener) { mLifecycleEventListeners.remove(listener); } + public Map> getAllPerformanceCounters() { + Map> totalPerfMap = + new HashMap<>(); + if (mCatalystInstance != null) { + for (NativeModule nativeModule : mCatalystInstance.getNativeModules()) { + if (nativeModule instanceof PerformanceCounter) { + PerformanceCounter perfCounterModule = (PerformanceCounter) nativeModule; + totalPerfMap.put(nativeModule.getName(), perfCounterModule.getPerformanceCounters()); + } + } + } + return totalPerfMap; + } + public void addActivityEventListener(ActivityEventListener listener) { mActivityEventListeners.add(listener); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java index 18600f3c4384dd..fd8f76c307c941 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIImplementation.java @@ -46,6 +46,9 @@ public class UIImplementation { private final int[] mMeasureBuffer = new int[4]; private final ReactApplicationContext mReactContext; + private double mLayoutCount = 0.0; + private double mLayoutTimer = 0.0; + public UIImplementation(ReactApplicationContext reactContext, List viewManagers) { this(reactContext, new ViewManagerRegistry(viewManagers)); } @@ -146,6 +149,14 @@ public void updateRootNodeSize( } } + public double getLayoutCount() { + return mLayoutCount; + } + + public double getLayoutTimer() { + return mLayoutTimer; + } + /** * Invoked by React to create a new node with a given tag, class name and properties. */ @@ -739,10 +750,13 @@ protected void calculateRootLayout(ReactShadowNode cssRoot) { SystraceMessage.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "cssRoot.calculateLayout") .arg("rootTag", cssRoot.getReactTag()) .flush(); + double startTime = (double) System.nanoTime(); try { cssRoot.calculateLayout(mLayoutContext); } finally { Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); + mLayoutTimer = mLayoutTimer + ((double)System.nanoTime() - startTime)/ 1000000000.0; + mLayoutCount = mLayoutCount + 1; } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java index ce32ea442e8220..7e6c389cda9185 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java @@ -12,6 +12,7 @@ import javax.annotation.Nullable; import java.util.List; +import java.util.HashMap; import java.util.Map; import com.facebook.common.logging.FLog; @@ -19,6 +20,7 @@ import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.OnBatchCompleteListener; +import com.facebook.react.bridge.PerformanceCounter; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; @@ -60,7 +62,7 @@ * TODO(5483063): Don't dispatch the view hierarchy at the end of a batch if no UI changes occurred */ public class UIManagerModule extends ReactContextBaseJavaModule implements - OnBatchCompleteListener, LifecycleEventListener { + OnBatchCompleteListener, LifecycleEventListener, PerformanceCounter { // Keep in sync with ReactIOSTagHandles JS module - see that file for an explanation on why the // increment here is 10 @@ -135,6 +137,13 @@ private static Map createConstants(List viewManager } } + public Map getPerformanceCounters() { + Map perfMap = new HashMap<>(); + perfMap.put("LayoutCount", mUIImplementation.getLayoutCount()); + perfMap.put("LayoutTimer", mUIImplementation.getLayoutTimer()); + return perfMap; + } + /** * Registers a new root view. JS can use the returned tag with manageChildren to add/remove * children to this view.