Show the frame rate the measured times allow in the overlay (#275)
game-maker / gate (push) Successful in 2m35s
game-maker / suite (push) Successful in 11m46s

The fps line of the performance overlay stops at the display's rate,
60 on most screens. It does not tell how much room a game has left.
The new top line answers that from the times the overlay measures.

- possibleFps in src/editor/frameMeter.ts is 1000 ms over the sum of
  the five areas, rounded down. It has no number while nothing took
  any time, and the overlay shows a dash then.
- The editor's share is in the sum, because it costs time while
  playing in the editor. A released game can do a little better.
- It is an upper bound. The GPU's time is not measured and not in it.
- e2e 59e reads the lines one further down and checks the new line
  against the times it measured itself.

Tests:
- Unit frame-meter: 11 passed (+2 for possibleFps)
- Gate: 197 files, 2855 tests, CHECK EXIT 0 (2853 + 2)
- e2e 59: ALL PASSED, 19 checks (+1), on melektaus-atx
- Counter-check: possibleFps without the editor's share fails the
  unit test
- The e2e total of 1602 is counted (1601 + 1), not measured

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 5.5 committed 2026-09-30 11:18:39 +02:00
1 parent 77f4c2c1a3
commit f14c4ecb77
4 files changed
+43 -8

No files matched your search

+11
View File
@@ -24,10 +24,21 @@ export interface PerformanceReading {
times: FrameTimes | null;
}
/**
* The frames a second the measured work would allow if nothing waited for the display: a second
* over what a frame takes in all areas. Only the main thread counts, the GPU's share is not in it.
*/
export function possibleFps(times: FrameTimes): number | null {
const total = FRAME_AREAS.reduce((sum, area) => sum + times[area], 0);
return total > 0 ? Math.floor(1000 / total) : null;
}
/** What the overlay shows, one area a line; a dash stands for what has not been measured yet. */
export function performanceLines({ fps, entities, times }: PerformanceReading): string[] {
const width = Math.max(...FRAME_AREAS.map((area) => LABELS[area].length));
const possible = `${(times && possibleFps(times)) ?? '–'} fps`;
return [
`${'Possible'.padEnd(width)} ${possible.padStart(9)}`,
`${fps ?? '–'} fps · ${entities} ${entities === 1 ? 'entity' : 'entities'}`,
...FRAME_AREAS.map((area) => {
const ms = times ? `${times[area].toFixed(2)} ms` : '– ms';