Skip to content

Commit

Permalink
fix: stop running Android FPS detection on flashlight start (#321)
Browse files Browse the repository at this point in the history
* fix: stop detecting Android FPS on execution

Android FPS detection was happening on flashlight start, whatever the command and OS used

* refactor(measure): get the fps from the measures directly

* prune(measure): remove now unneeded event

* test: update to 120FPS in tests
  • Loading branch information
Almouro authored Oct 28, 2024
1 parent ef7759a commit 4643b9a
Show file tree
Hide file tree
Showing 11 changed files with 43 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ Average Test Runtime
Time taken to run the test.
Can be helpful to measure Time To Interactive of your app, if the test is checking app start for instance.
Average FPS
60 FPS
Frame Per Second. Your app should display 60 Frames Per Second to give an impression of fluidity. This number should be close to 60, otherwise it will seem laggy.
120 FPS
Frame Per Second. Your app should display 120 Frames Per Second to give an impression of fluidity. This number should be close to 120, otherwise it will seem laggy.
See
Expand All @@ -34,7 +34,7 @@ RN JS Thread
0.5
s
High CPU usage by a single process can cause app unresponsiveness, even with low overall CPU usage. For instance, an overworked JS thread in a React Native app may lead to unresponsiveness despite maintaining 60 FPS.
High CPU usage by a single process can cause app unresponsiveness, even with low overall CPU usage. For instance, an overworked JS thread in a React Native app may lead to unresponsiveness despite maintaining 120 FPS.
Average RAM usage
375.8 MB
If an app consumes a large amount of RAM (random-access memory), it can impact the overall performance of the device and drain the battery more quickly.
Expand Down Expand Up @@ -106,11 +106,11 @@ Frame rate (FPS)
"data": [
{
"x": 0,
"y": 60
"y": 120
},
{
"x": 500,
"y": 60
"y": 120
}
]
}
Expand Down Expand Up @@ -752,7 +752,7 @@ exports[`flashlight measure interactive it displays measures: Web app with measu
<div
class="text-neutral-300 whitespace-pre"
>
60 FPS
120 FPS
</div>
<div
class="w-2"
Expand Down Expand Up @@ -782,7 +782,7 @@ exports[`flashlight measure interactive it displays measures: Web app with measu
<div
class="text-neutral-400 text-sm"
>
Frame Per Second. Your app should display 60 Frames Per Second to give an impression of fluidity. This number should be close to 60, otherwise it will seem laggy.
Frame Per Second. Your app should display 120 Frames Per Second to give an impression of fluidity. This number should be close to 120, otherwise it will seem laggy.
<br />
See
<a
Expand Down Expand Up @@ -942,7 +942,7 @@ exports[`flashlight measure interactive it displays measures: Web app with measu
- RN JS Thread for 0.5s
</p>
</div>
High CPU usage by a single process can cause app unresponsiveness, even with low overall CPU usage. For instance, an overworked JS thread in a React Native app may lead to unresponsiveness despite maintaining 60 FPS.
High CPU usage by a single process can cause app unresponsiveness, even with low overall CPU usage. For instance, an overworked JS thread in a React Native app may lead to unresponsiveness despite maintaining 120 FPS.
</div>
</div>
</div>
Expand Down Expand Up @@ -1100,11 +1100,11 @@ exports[`flashlight measure interactive it displays measures: Web app with measu
"data": [
{
"x": 0,
"y": 60
"y": 120
},
{
"x": 500,
"y": 60
"y": 120
}
]
}
Expand Down Expand Up @@ -3813,7 +3813,7 @@ Time taken to run the test.
Can be helpful to measure Time To Interactive of your app, if the test is checking app start for instance.
Average FPS
-
Frame Per Second. Your app should display 60 Frames Per Second to give an impression of fluidity. This number should be close to 60, otherwise it will seem laggy.
Frame Per Second. Your app should display 120 Frames Per Second to give an impression of fluidity. This number should be close to 120, otherwise it will seem laggy.
See
Expand All @@ -3829,7 +3829,7 @@ An app might run at high frame rates, such as 60 FPS or higher, but might be usi
High CPU Usage
-
Impacted threads:
High CPU usage by a single process can cause app unresponsiveness, even with low overall CPU usage. For instance, an overworked JS thread in a React Native app may lead to unresponsiveness despite maintaining 60 FPS.
High CPU usage by a single process can cause app unresponsiveness, even with low overall CPU usage. For instance, an overworked JS thread in a React Native app may lead to unresponsiveness despite maintaining 120 FPS.
Average RAM usage
-
If an app consumes a large amount of RAM (random-access memory), it can impact the overall performance of the device and drain the battery more quickly.
Expand Down Expand Up @@ -4146,7 +4146,7 @@ exports[`flashlight measure interactive it displays measures: Web app with no me
<div
class="text-neutral-400 text-sm"
>
Frame Per Second. Your app should display 60 Frames Per Second to give an impression of fluidity. This number should be close to 60, otherwise it will seem laggy.
Frame Per Second. Your app should display 120 Frames Per Second to give an impression of fluidity. This number should be close to 120, otherwise it will seem laggy.
<br />
See
<a
Expand Down Expand Up @@ -4297,7 +4297,7 @@ exports[`flashlight measure interactive it displays measures: Web app with no me
Impacted threads:
</p>
</div>
High CPU usage by a single process can cause app unresponsiveness, even with low overall CPU usage. For instance, an overworked JS thread in a React Native app may lead to unresponsiveness despite maintaining 60 FPS.
High CPU usage by a single process can cause app unresponsiveness, even with low overall CPU usage. For instance, an overworked JS thread in a React Native app may lead to unresponsiveness despite maintaining 120 FPS.
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,22 @@ export const ServerSocketConnectionApp = ({ socket, url }: { socket: SocketType;
setState((state) =>
addNewResultReducer(
state,
`${bundleId}${state.results.length > 0 ? ` (${state.results.length + 1})` : ""}`
`${bundleId}${state.results.length > 0 ? ` (${state.results.length + 1})` : ""}`,
profiler.detectDeviceRefreshRate()
)
);

socket.on(SocketEvents.START, async () => {
const refreshRate = profiler.detectDeviceRefreshRate();
setState({
isMeasuring: true,
refreshRate,
});

if (!state.bundleId) {
Logger.error("No bundle id provided");
return;
}

profiler.installProfilerOnDevice();
performanceMeasureRef.current = new PerformanceMeasurer(state.bundleId, {
recordOptions: {
record: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ export interface SocketData {
isMeasuring: boolean;
bundleId: string | null;
results: TestCaseResult[];
refreshRate: number;
}

export interface ServerToClientEvents {
Expand Down Expand Up @@ -46,7 +45,6 @@ export enum SocketEvents {
RESET = "reset",
AUTODETECT_BUNDLE_ID = "autodetectBundleId",
SET_BUNDLE_ID = "setBundleId",
AUTODETECT_REFRESH_RATE = "autodetectRefreshRate",
UPDATE_STATE = "updateState",
SEND_ERROR = "sendError",
PING = "ping",
Expand Down
9 changes: 6 additions & 3 deletions packages/commands/measure/src/server/socket/socketState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ export const useSocketState = (socket: SocketType) => {
isMeasuring: false,
bundleId: null,
results: [],
refreshRate: 60,
});

const setState = (
Expand Down Expand Up @@ -47,7 +46,11 @@ export const updateMeasuresReducer = (state: SocketData, measures: Measure[]): S
],
});

export const addNewResultReducer = (state: SocketData, name: string): SocketData => ({
export const addNewResultReducer = (
state: SocketData,
name: string,
refreshRate: number
): SocketData => ({
...state,
results: [
...state.results,
Expand All @@ -56,7 +59,7 @@ export const addNewResultReducer = (state: SocketData, name: string): SocketData
iterations: [],
status: "SUCCESS",
specs: {
refreshRate: state.refreshRate,
refreshRate,
},
},
],
Expand Down
10 changes: 0 additions & 10 deletions packages/commands/measure/src/server/useBundleIdControls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,9 @@ export const useBundleIdControls = (
}
});

socket.on(SocketEvents.AUTODETECT_REFRESH_RATE, () => {
stop();

const refreshRate = profiler.detectDeviceRefreshRate();
setState({
refreshRate,
});
});

return () => {
socket.removeAllListeners(SocketEvents.SET_BUNDLE_ID);
socket.removeAllListeners(SocketEvents.AUTODETECT_BUNDLE_ID);
socket.removeAllListeners(SocketEvents.AUTODETECT_REFRESH_RATE);
};
}, [setState, socket, stop]);
};
2 changes: 0 additions & 2 deletions packages/commands/measure/src/webapp/useMeasures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,8 @@ export const useMeasures = () => {

return {
bundleId: state?.bundleId ?? null,
refreshRate: state?.refreshRate ?? 60,
autodetect: () => {
socket.emit(SocketEvents.AUTODETECT_BUNDLE_ID);
socket.emit(SocketEvents.AUTODETECT_REFRESH_RATE);
},
setBundleId: (bundleId: string) => {
socket.emit(SocketEvents.SET_BUNDLE_ID, bundleId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ exports[`PerformanceMeasurer handles c++ errors correctly 1`] = `
"queued-work-loo (3)": 0,
},
},
"fps": 60,
"fps": 120,
"ram": 375.76171875,
"time": 500,
},
Expand Down Expand Up @@ -120,7 +120,7 @@ exports[`PerformanceMeasurer handles c++ errors correctly 1`] = `
"queued-work-loo (3)": 0,
},
},
"fps": 60,
"fps": 120,
"ram": 375.76171875,
"time": 1000,
},
Expand Down
2 changes: 2 additions & 0 deletions packages/commands/test/src/utils/test/mockChildProcess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ jest.mock("child_process", () => {
return "arm64-v8a";
case "adb shell getprop ro.build.version.sdk":
return "30";
case 'adb shell dumpsys display | grep -E "mRefreshRate|DisplayDeviceInfo"':
return "fps=120";
case "adb shell setprop debug.hwui.profile true":
case "adb shell atrace --async_stop 1>/dev/null":
case "adb shell chmod 755 /data/local/tmp/BAMPerfProfiler":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,6 @@ export const parseLine = (
};
};

const TARGET_FRAME_RATE = refreshRateManager.getRefreshRate();
const TARGET_FRAME_TIME = 1000 / TARGET_FRAME_RATE;
Logger.info(`Target frame rate: ${TARGET_FRAME_RATE} Hz`);

export class FrameTimeParser {
private methodStartedCount = 0;
private doFrameStartedTimeStamp: number | null = null;
Expand Down Expand Up @@ -97,6 +93,9 @@ ${error instanceof Error ? error.message : error}`);
static getFps(frameTimes: number[], timeInterval: number, uiCpuUsage: number) {
const frameCount = frameTimes.length;

const TARGET_FRAME_RATE = refreshRateManager.getRefreshRate();
const TARGET_FRAME_TIME = 1000 / TARGET_FRAME_RATE;

const totalFrameTime = frameTimes.reduce(
(sum, time) => sum + Math.max(TARGET_FRAME_TIME, time),
0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
import { executeCommand } from "./shell";
import { Logger } from "@perf-profiler/logger";

const DEFAULT_FRAME_RATE = 60;

function deviceRefreshRateManager() {
let refreshRate = 60; // Default to 60 fps
let refreshRate: number | null = null;

return {
getRefreshRate: () => refreshRate,
isInitialized: () => refreshRate !== null,
getRefreshRate: () => {
if (refreshRate === null) {
throw new Error("Refresh rate not initialized");
}
return refreshRate;
},
setRefreshRate: () => {
try {
refreshRate = detectCurrentDeviceRefreshRate();
Logger.info(`Target frame rate: ${refreshRate} Hz`);
} catch (e) {
Logger.error(`Could not detect device refresh rate: ${e}`);
refreshRate = DEFAULT_FRAME_RATE;
}
},
};
Expand Down Expand Up @@ -47,6 +57,5 @@ export const detectCurrentDeviceRefreshRate = () => {
};

const refreshRateManager = deviceRefreshRateManager();
refreshRateManager.setRefreshRate();

export { refreshRateManager };
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export class AndroidProfiler extends UnixProfiler {

installProfilerOnDevice(): void {
super.installProfilerOnDevice();
if (!refreshRateManager.isInitialized()) refreshRateManager.setRefreshRate();
if (!this.aTraceProcess) this.startATrace();
}

Expand Down

0 comments on commit 4643b9a

Please sign in to comment.