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 d83fe1be13db05..d07d4ae28a28dd 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java @@ -70,6 +70,15 @@ public void initializeWithInstance(CatalystInstance catalystInstance) { mJSMessageQueueThread = queueConfig.getJSQueueThread(); } + public void resetPerfStats() { + if (mNativeModulesMessageQueueThread != null) { + mNativeModulesMessageQueueThread.resetPerfStats(); + } + if (mJSMessageQueueThread != null) { + mJSMessageQueueThread.resetPerfStats(); + } + } + public void setNativeModuleCallExceptionHandler( @Nullable NativeModuleCallExceptionHandler nativeModuleCallExceptionHandler) { mNativeModuleCallExceptionHandler = nativeModuleCallExceptionHandler; diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/MessageQueueThread.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/MessageQueueThread.java index 91014ed3fbdbc3..ca3fda84c7e296 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/MessageQueueThread.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/MessageQueueThread.java @@ -60,9 +60,16 @@ public interface MessageQueueThread { void quitSynchronous(); /** - * Returns the time in milliseconds at which this thread was started. This + * Returns the perf counters taken when the framework was started. This * method is intended to be used for instrumentation purposes. */ @DoNotStrip - long getStartTimeMillis(); + MessageQueueThreadPerfStats getPerfStats(); + + /** + * Resets the perf counters. This is useful if the RN threads are being re-used. + * This method is intended to be used for instrumentation purposes. + */ + @DoNotStrip + void resetPerfStats(); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/MessageQueueThreadImpl.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/MessageQueueThreadImpl.java index 11ce7a40e80577..76ce66b70c2654 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/MessageQueueThreadImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/MessageQueueThreadImpl.java @@ -32,25 +32,25 @@ public class MessageQueueThreadImpl implements MessageQueueThread { private final Looper mLooper; private final MessageQueueThreadHandler mHandler; private final String mAssertionErrorMessage; - private long mStartTimeMillis; + private MessageQueueThreadPerfStats mPerfStats; private volatile boolean mIsFinished = false; private MessageQueueThreadImpl( String name, Looper looper, QueueThreadExceptionHandler exceptionHandler) { - this(name, looper, exceptionHandler, -1); + this(name, looper, exceptionHandler, null); } private MessageQueueThreadImpl( String name, Looper looper, QueueThreadExceptionHandler exceptionHandler, - long startTimeMillis) { + MessageQueueThreadPerfStats stats) { mName = name; mLooper = looper; mHandler = new MessageQueueThreadHandler(looper, exceptionHandler); - mStartTimeMillis = startTimeMillis; + mPerfStats = stats; mAssertionErrorMessage = "Expected to be called from the '" + getName() + "' thread!"; } @@ -139,8 +139,27 @@ public void quitSynchronous() { @DoNotStrip @Override - public long getStartTimeMillis() { - return mStartTimeMillis; + public MessageQueueThreadPerfStats getPerfStats() { + return mPerfStats; + } + + @DoNotStrip + @Override + public void resetPerfStats() { + assignToPerfStats(mPerfStats, -1, -1); + runOnQueue(new Runnable() { + @Override + public void run() { + long wallTime = SystemClock.uptimeMillis(); + long cpuTime = SystemClock.currentThreadTimeMillis(); + assignToPerfStats(mPerfStats, wallTime, cpuTime); + } + }); + } + + private static void assignToPerfStats(MessageQueueThreadPerfStats stats, long wall, long cpu) { + stats.wallTime = wall; + stats.cpuTime = cpu; } public Looper getLooper() { @@ -197,7 +216,7 @@ private static MessageQueueThreadImpl startNewBackgroundThread( final String name, long stackSize, QueueThreadExceptionHandler exceptionHandler) { - final SimpleSettableFuture> dataFuture = new SimpleSettableFuture<>(); + final SimpleSettableFuture> dataFuture = new SimpleSettableFuture<>(); long startTimeMillis; Thread bgThread = new Thread(null, new Runnable() { @@ -205,13 +224,17 @@ private static MessageQueueThreadImpl startNewBackgroundThread( public void run() { Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY); Looper.prepare(); - dataFuture.set(new Pair<>(Looper.myLooper(), SystemClock.uptimeMillis())); + MessageQueueThreadPerfStats stats = new MessageQueueThreadPerfStats(); + long wallTime = SystemClock.uptimeMillis(); + long cpuTime = SystemClock.currentThreadTimeMillis(); + assignToPerfStats(stats, wallTime, cpuTime); + dataFuture.set(new Pair<>(Looper.myLooper(), stats)); Looper.loop(); } }, "mqt_" + name, stackSize); bgThread.start(); - Pair pair = dataFuture.getOrThrow(); + Pair pair = dataFuture.getOrThrow(); return new MessageQueueThreadImpl(name, pair.first, exceptionHandler, pair.second); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/MessageQueueThreadPerfStats.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/MessageQueueThreadPerfStats.java new file mode 100644 index 00000000000000..7b7866645c1a52 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/MessageQueueThreadPerfStats.java @@ -0,0 +1,16 @@ +/** + * 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.bridge.queue; + +/** + * This class holds perf counters' values at the beginning of an RN startup. + */ +public class MessageQueueThreadPerfStats { + public long wallTime; + public long cpuTime; +}