diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/FpsView.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/FpsView.java index dfefbc10c..47d340b05 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/FpsView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/FpsView.java @@ -43,7 +43,7 @@ public class FpsView extends FrameLayout { mTextView = (TextView) findViewById(R.id.fps_text); mFrameCallback = new FpsDebugFrameCallback(Choreographer.getInstance(), reactContext); mFPSMonitorRunnable = new FPSMonitorRunnable(); - setCurrentFPS(0, 0); + setCurrentFPS(0, 0, 0, 0); } @Override @@ -61,11 +61,13 @@ public class FpsView extends FrameLayout { mFPSMonitorRunnable.stop(); } - private void setCurrentFPS(double currentFPS, double currentJSFPS) { + private void setCurrentFPS(double currentFPS, double currentJSFPS, int droppedUIFrames, int total4PlusFrameStutters) { String fpsString = String.format( Locale.US, - "UI FPS: %.1f\nJS FPS: %.1f", + "UI: %.1f fps\n%d dropped so far\n%d stutters (4+) so far\nJS: %.1f fps", currentFPS, + droppedUIFrames, + total4PlusFrameStutters, currentJSFPS); mTextView.setText(fpsString); FLog.d(ReactConstants.TAG, fpsString); @@ -77,14 +79,17 @@ public class FpsView extends FrameLayout { private class FPSMonitorRunnable implements Runnable { private boolean mShouldStop = false; + private int mTotalFramesDropped = 0; + private int mTotal4PlusFrameStutters = 0; @Override public void run() { if (mShouldStop) { return; } - - setCurrentFPS(mFrameCallback.getFPS(), mFrameCallback.getJSFPS()); + mTotalFramesDropped += mFrameCallback.getExpectedNumFrames() - mFrameCallback.getNumFrames(); + mTotal4PlusFrameStutters += mFrameCallback.get4PlusFrameStutters(); + setCurrentFPS(mFrameCallback.getFPS(), mFrameCallback.getJSFPS(), mTotalFramesDropped, mTotal4PlusFrameStutters); mFrameCallback.reset(); postDelayed(this, UPDATE_INTERVAL_MS); diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/debug/FpsDebugFrameCallback.java b/ReactAndroid/src/main/java/com/facebook/react/modules/debug/FpsDebugFrameCallback.java index 1e63f525d..71400867e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/debug/FpsDebugFrameCallback.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/debug/FpsDebugFrameCallback.java @@ -41,6 +41,7 @@ public class FpsDebugFrameCallback implements Choreographer.FrameCallback { public final int totalFrames; public final int totalJsFrames; public final int totalExpectedFrames; + public final int total4PlusFrameStutters; public final double fps; public final double jsFps; public final int totalTimeMs; @@ -49,12 +50,14 @@ public class FpsDebugFrameCallback implements Choreographer.FrameCallback { int totalFrames, int totalJsFrames, int totalExpectedFrames, + int total4PlusFrameStutters, double fps, double jsFps, int totalTimeMs) { this.totalFrames = totalFrames; this.totalJsFrames = totalJsFrames; this.totalExpectedFrames = totalExpectedFrames; + this.total4PlusFrameStutters = total4PlusFrameStutters; this.fps = fps; this.jsFps = jsFps; this.totalTimeMs = totalTimeMs; @@ -72,6 +75,8 @@ public class FpsDebugFrameCallback implements Choreographer.FrameCallback { private long mFirstFrameTime = -1; private long mLastFrameTime = -1; private int mNumFrameCallbacks = 0; + private int mExpectedNumFramesPrev = 0; + private int m4PlusFrameStutters = 0; private int mNumFrameCallbacksWithBatchDispatches = 0; private boolean mIsRecordingFpsInfoAtEachFrame = false; private @Nullable TreeMap mTimeToFps; @@ -103,18 +108,25 @@ public class FpsDebugFrameCallback implements Choreographer.FrameCallback { } mNumFrameCallbacks++; + int expectedNumFrames = getExpectedNumFrames(); + int framesDropped = expectedNumFrames - mExpectedNumFramesPrev - 1; + if (framesDropped >= 4) { + m4PlusFrameStutters++; + } if (mIsRecordingFpsInfoAtEachFrame) { Assertions.assertNotNull(mTimeToFps); FpsInfo info = new FpsInfo( getNumFrames(), getNumJSFrames(), - getExpectedNumFrames(), + expectedNumFrames, + m4PlusFrameStutters, getFPS(), getJSFPS(), getTotalTimeMS()); mTimeToFps.put(System.currentTimeMillis(), info); } + mExpectedNumFramesPrev = expectedNumFrames; mChoreographer.postFrameCallback(this); } @@ -168,6 +180,10 @@ public class FpsDebugFrameCallback implements Choreographer.FrameCallback { return expectedFrames; } + public int get4PlusFrameStutters() { + return m4PlusFrameStutters; + } + public int getTotalTimeMS() { return (int) ((double) mLastFrameTime - mFirstFrameTime) / 1000000; } @@ -189,6 +205,7 @@ public class FpsDebugFrameCallback implements Choreographer.FrameCallback { mFirstFrameTime = -1; mLastFrameTime = -1; mNumFrameCallbacks = 0; + m4PlusFrameStutters = 0; mNumFrameCallbacksWithBatchDispatches = 0; mIsRecordingFpsInfoAtEachFrame = false; mTimeToFps = null; diff --git a/ReactAndroid/src/main/res/devsupport/layout/fps_view.xml b/ReactAndroid/src/main/res/devsupport/layout/fps_view.xml index fc76be61e..468caa9f3 100644 --- a/ReactAndroid/src/main/res/devsupport/layout/fps_view.xml +++ b/ReactAndroid/src/main/res/devsupport/layout/fps_view.xml @@ -7,12 +7,12 @@ android:id="@+id/fps_text" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_margin="5dp" - android:background="#aa141823" + android:layout_margin="3dp" + android:background="#a4141823" android:gravity="right" android:layout_gravity="top|right" - android:padding="5dp" + android:padding="3dp" android:textColor="@android:color/white" - android:textSize="16sp" + android:textSize="11sp" />