Skip to content

perf(touch): skip unchanged window updates and add E7 replay - #18

Merged
doodlewind merged 3 commits into
mainfrom
perf/touch-e7-frame-time
Sep 17, 2026
Merged

doodlewind merged 3 commits into
mainfrom
perf/touch-e7-frame-time

Conversation

@doodlewind

@doodlewind doodlewind commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

The touch painter resent 179 native property writes through 84 calls on every settled frame. Cache painter-owned values, skip unchanged window batches, and stop settled springs before evaluating their exponential. Mounted app state, gesture coordinates, spring targets, recency, and animation timing stay intact.

Add a bounded E7 packed-input workload and CODA profiling/readback. Replay advances with PocketJS's virtual frame clock so slow frames cannot skip whole contacts; phase selection uses that clock while FPS uses real frame intervals. Reject incomplete traces, inactive-window samples, and viewport mismatches. USB transfers use 512-byte payloads inside CODA's router framing; measurements contain no USB polling.

Device validation

Two valid native replays per build; 360 × 640, 120 warmup frames, 30 virtual seconds. All four report inactive_frames=0; control runs contain 901 frames and optimized runs 1,801. The control uses the original guest, software-float core, QuickJS O0 and 30 Hz host; the candidate uses both PRs at 60 Hz. Values below are the range across the two runs, not the result of one selected pass.

Gesture phase Control FPS Optimized FPS Control frame p95 Optimized frame p95
Home paging 24.81–24.83 54.77–56.70 43–44 ms 20–21 ms
App → Home 24.29–24.32 53.06–53.08 47 ms 22–23 ms
Stacked switcher 13.16–13.17 30.09–30.18 91 ms 42 ms

The switcher still misses 60 FPS: roughly 8 ms JS, 5.8 ms scene generation, 1.6 ms geometry, 1.6 ms buffer upload and 14.4 ms GLES submission per frame. The GPU is active, but those wall times do not isolate GPU execution from driver waits. An exploratory quarter-pixel-area run did not materially improve throughput; this points toward CPU/submission overhead, not a proven Symbian or hardware ceiling. Its earlier wall-clock replay is excluded from the table. Font-padding fill batching reduces idle-app batches from 25 to 17; the switcher only loses one batch (~114.5 → 113.5), so it is a small part of the overall improvement.

The two-run idle-app average is variable (the first optimized run contains an outlier), so the table focuses on the requested gesture phases and does not claim uniform frame pacing everywhere.

The connected E7 reports OpenGL ES 2.0 / Broadcom / VideoCore III HW, and VFPv2 through HAL. These combined results include the runtime work in PocketJS #444: optimized QuickJS, hardware floating point, 60 Hz scheduling, and GLES submission work. They are not an estimate of this shell patch in isolation.

Checks

Latest-head CI passes both All shells + macOS desktop and Linux distribution + WASM preview.

  • bun run check:touch: typecheck, 47 tests / 5,866 assertions, and 7 Python CODA protocol tests pass.
  • Root bun run check: 221 Bun tests plus the 7 Python tests passed after the painter changes; the final replay changes pass the focused check above.
  • 2,700 software-rendered frames across 30/60 Hz match the previous painter exactly. Native call counts drop from 75,622 to 6,442 at 30 Hz and 151,222 to 12,517 at 60 Hz; a settled frame makes zero painter calls.
  • Synthetic analyzer validation distinguishes virtual phases from wall-clock FPS and rejects incomplete, inactive, and rotated runs.
  • The final settled native E7 screenshot matches the control at all 230,400 pixels.

Reproduce

Build the shell manifest against the PocketJS #444 checkout, with --frame-rate 60 --perf-trace; the shell README contains the full make/profile/analyze commands. The workload is 30 virtual seconds at 360 × 640 after 120 warmup frames. No screenshots or file writes occur inside the measured interval. Profiling builds keep the device awake and lock replay orientation; the installed normal build retains automatic orientation and normal sleep.

Build identities: runtime 2453d60cba877e9cd0629ad0d19d36f3c94c46f8, shell 6a9238607ab03129c79998f067353d8df50cc023; package UID 0xEA360236, executable PocketJsPocketshellToucEA360236.exe.

Package SIS version SIS SHA-256
Control with matched replay harness 0.2.28 b9456b889e3b7e5ef655595d06ff647f24a7dda5ae96c4c1ec3fa91731537b6d
Optimized profiling build 0.2.27 69502e76051a3352d27b26526ea7fd1c94da5a446da98b57aba7c3f8a40126f3
Normal build, tracing disabled 0.2.31 31d77a8259efdfed4a9b0acd96f5bd3cca4a548ceca24fa8355fb09d39648677

The normal SIS was transferred through MTP and read back byte-for-byte, installed through CODA, and launched as p1897; the installed package reports version 0.2.31. The replay file is empty and the temporary wake helper (0xE7A11037) has been uninstalled. A surviving normal-build process is deployment evidence; the profiling screenshot and replay are the rendered-frame evidence.

The normal build uses the standard CLI's built-in Rust core path, with no --core-library override. Its guest SHA-256 is 1abe2d0f39a0fa1ac27016a48c383524347e115e55db16cf4fb75b3452298a47, PAK 5fef1b87a973913e8f2076c546199e6525362ac020b846f189ad9ff8fde19e7f, and core 04f196f0a4dff7be05deda6888d2745c908681a7e711fc08280643d756f1a912.

This PR remains stacked on #17. vendor/pocketjs is unchanged; its pin can move after the upstream runtime change lands. Native replay starts at the packed-input boundary, so physical touch delivery, GPU execution time, and display scanout are outside the measurement. The results improve E7 rendering throughput but do not establish iPod-equivalent latency or sustained 60 FPS in the switcher. Per-run traces, SIS files and screenshots remain under ignored .pocket-build/validation/touch/e7-performance/.

@doodlewind
doodlewind marked this pull request as ready for review September 17, 2026 19:18
@doodlewind
doodlewind changed the base branch from fix/touch-home-recency-and-return to main September 17, 2026 21:20
@doodlewind
doodlewind merged commit 57175ef into main Sep 17, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant