From 2330843fa71e303e123b90cf23b78453456e22bf Mon Sep 17 00:00:00 2001 From: Max Sherman Date: Mon, 3 Dec 2018 11:44:21 -0800 Subject: [PATCH] Add API for instrumentation to learn the starting wall time of bg threads Summary: Computing things like "page faults since this thread was created" or "cpu time spent on this thread since it was created" is pretty easy - just measure it when you want it. However, if you want to know "how much wall time has elapsed since this thread was created" you need to record some timing info when the thread is created. This diff adds a an API for querying that from the RN thread holder abstraction. Reviewed By: alexeylang Differential Revision: D13246235 fbshipit-source-id: d36af61dbe27f662980fe508b2644e9d5255bb7e --- .../bridge/queue/MessageQueueThread.java | 7 +++++ .../bridge/queue/MessageQueueThreadImpl.java | 29 +++++++++++++++---- 2 files changed, 30 insertions(+), 6 deletions(-) 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 732d2f897ceed2..91014ed3fbdbc3 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 @@ -58,4 +58,11 @@ public interface MessageQueueThread { */ @DoNotStrip void quitSynchronous(); + + /** + * Returns the time in milliseconds at which this thread was started. This + * method is intended to be used for instrumentation purposes. + */ + @DoNotStrip + long getStartTimeMillis(); } 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 d169a578e70c4e..11ce7a40e80577 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 @@ -10,9 +10,10 @@ import java.util.concurrent.Callable; import java.util.concurrent.Future; +import android.os.SystemClock; import android.os.Looper; import android.os.Process; - +import android.util.Pair; import com.facebook.common.logging.FLog; import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.AssertionException; @@ -31,15 +32,25 @@ public class MessageQueueThreadImpl implements MessageQueueThread { private final Looper mLooper; private final MessageQueueThreadHandler mHandler; private final String mAssertionErrorMessage; + private long mStartTimeMillis; private volatile boolean mIsFinished = false; private MessageQueueThreadImpl( String name, Looper looper, QueueThreadExceptionHandler exceptionHandler) { + this(name, looper, exceptionHandler, -1); + } + + private MessageQueueThreadImpl( + String name, + Looper looper, + QueueThreadExceptionHandler exceptionHandler, + long startTimeMillis) { mName = name; mLooper = looper; mHandler = new MessageQueueThreadHandler(looper, exceptionHandler); + mStartTimeMillis = startTimeMillis; mAssertionErrorMessage = "Expected to be called from the '" + getName() + "' thread!"; } @@ -126,6 +137,12 @@ public void quitSynchronous() { } } + @DoNotStrip + @Override + public long getStartTimeMillis() { + return mStartTimeMillis; + } + public Looper getLooper() { return mLooper; } @@ -180,21 +197,21 @@ private static MessageQueueThreadImpl startNewBackgroundThread( final String name, long stackSize, QueueThreadExceptionHandler exceptionHandler) { - final SimpleSettableFuture looperFuture = new SimpleSettableFuture<>(); + final SimpleSettableFuture> dataFuture = new SimpleSettableFuture<>(); + long startTimeMillis; Thread bgThread = new Thread(null, new Runnable() { @Override public void run() { Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY); Looper.prepare(); - - looperFuture.set(Looper.myLooper()); + dataFuture.set(new Pair<>(Looper.myLooper(), SystemClock.uptimeMillis())); Looper.loop(); } }, "mqt_" + name, stackSize); bgThread.start(); - Looper myLooper = looperFuture.getOrThrow(); - return new MessageQueueThreadImpl(name, myLooper, exceptionHandler); + Pair pair = dataFuture.getOrThrow(); + return new MessageQueueThreadImpl(name, pair.first, exceptionHandler, pair.second); } }