Skip to content

Reduce Android frame delays, idle redraws, and image work - #112

Merged
ymote merged 17 commits into
mainfrom
perf/widget-update-guards
Oct 9, 2026
Merged

ymote merged 17 commits into
mainfrom
perf/widget-update-guards

Conversation

@ymote

@ymote ymote commented Oct 8, 2026 •

Copy link
Copy Markdown

Android chat drags could wait nearly a refresh because native AChoreographer ran before Java View delivered batched input. Schedule rendering through a static Java Choreographer callback after View input, retaining no Activity and preserving the native callback-chain guard, JNI signature, and fallback for older packagers or no_android_choreographer.

Additional changes:

  • Advance the first PortalList/ScrollBar fling frame immediately, then use measured frame intervals.
  • Add a direct PortalList::set_capture_overload setter without script reapplication, redraw, or auto-tail reset.
  • Clear stale PortalList drag samples when a child takes pointer capture. Long-press selection previously transferred capture without FingerUp, suppressing later handle movements; existing overscroll still settles.
  • Stop closed Modal/Tooltip fullscreen draws, skip unused recursive GPU inventories, invalidate list topology only after retention removes entries, and avoid unchanged setter invalidations while preserving side effects.
  • Blink the default TextInput caret with discrete states instead of 50 ms fades.
  • Bound opt-in widget-cost attribution at 1,024 operation/type pairs. Rinx retains all 353 observed entries without overflow; presentation measurements disable profiling.

Backport official Makepad #1288 (711521dbf): normalized Android navigation with Emphasized easing after initial drawing, accurate Bezier solving, stale ShowTextIME removal, and deferred IME hiding. Adapt this to the fork's two-view pool and event APIs, and update the notes caller for width-free navigation methods.

Backport official Makepad #1296 (95e0ad5a4): shared natural-time image animation, offscreen pause, APNG/WebP compositing, compact atlases, natural-size texture metadata, and optional display-sized decoding with larger-cache reuse. Preserve asynchronous eviction recovery and error reporting. APIs absent from this fork, including image slice/crop options and cancellation scopes, are not introduced.

Main through d955125e9 is included, preserving #113 and #114. Rinx integration: hagency-org/Rinx#85. Merge with the tested commit retained in main history because Rinx pins it directly. This targets the OctoSense fork; the additional changes have not been merged into official Makepad.

Validation

Exact tested revisions: Rinx 297903d1043023d8992136a0e622fdf92df82795, Makepad 07825feab684d21f69b4afb1ec60f623c13f9183.

Test Baseline Candidate
Hidden native Metal: median callbacks / 8 s focused idle 207 13
Hidden native Metal: callbacks / 20 s typing/deletion 539 87
Mate 70 Air: median callbacks / 8 s focused idle 69 17
Mate 70 Air: callbacks / 20 s typing/deletion 156 48
Mate 70 Air: presentation intervals >25 ms, 12 native swipes 35/1,784 (1.96%) 26/1,781 (1.46%)

The signed HarmonyOS release packages ran on Mate 70 Air (SUP-AL90, API 24, 60 Hz). Candidate median/p95 presentation intervals were 16.622/16.665 ms, maximum 33.294 ms. The baseline includes one unresolved 1,047 ms first-interval gap (swipe setup versus app latency), retained in raw totals. These small samples do not establish a robust scrolling speedup.

macOS and HarmonyOS used an isolated 160-message Matrix fixture; typing inserted and deleted an unsent draft. The final instrument-only and native-swipe protocols passed, with no messages sent. Phone scrolling used native touch injection, profiling disabled, and RenderService timestamps for the owned surface. Native drawable captures verified rendering. Invalid USB-input and stale-history trials were excluded. Detailed captures/reports remain local; owned test sessions are closed.

Redmi Note 12 final release: long-press and handle-drag selection extends through wrapped text without moving the conversation. Focused idle recorded 1.91 presents/s versus the earlier baseline's 8.70/s. With profiling off, 24 gestures recorded 7/2,281 missed refresh opportunities (0.307%), max 33.421 ms; a same-session previous-build control recorded 7/2,252 (0.311%). No additional scrolling gain is established by that comparison. Current-head OnePlus runtime validation is not claimed.

Rinx CI passes all three checks; release unit tests record 355 passed, 0 failed, 2 existing ignores. Makepad widget tests record 292 passed and three failures also reproduced on the baseline: desktop_style::tests::mobile_typefaces_keep_symbol_fallbacks_across_appearances, widget_tree::tests::test_observe_and_find_single_node, and widget_tree::tests::test_property_patch_no_structural_rebuild. Widget compile checks pass on macOS, Android, Wasm, Linux, Windows, and OpenHarmony using installed SDKs. Existing warnings remain; iOS is untested because its Rust target is absent. Draw/platform suites passed 151/252 tests on the integrated parent; the final Makepad change is limited to PortalList. These are compile/unit results, not six-platform runtime claims.

Remaining limits

This is not a hitch-free, battery-saving, memory-leak, or native-app-parity claim. Cold room opening (about 276 ms in the earlier Android capture), safe cross-message rich-text recycling, gradual memory growth, and startup-theme persistence remain unresolved. Image-memory savings were not quantified.

Hidden macOS windows use timer pacing, so those results establish callback work, not display frame rate or physical input latency. Profiler-off scroll CPU medians were 0.99 -> 0.90 seconds in small runs under background load; no causal gain is claimed. Combined typing/scroll captures had glyph artifacts in both revisions; separate scroll-only captures rendered correctly, leaving visible-window follow-up.

The OHOS painted-frame counter remains unwired and was not used. Mobile chat children are missing from widget inspection, so native-image checks validated the composer outside timing intervals. The local fixture does not establish performance against a live encrypted server or under sustained thermal load.

@ymote ymote changed the title Avoid redundant property invalidation and attribute widget work Schedule Android rendering after View input and skip unused rendering work Oct 9, 2026
@ymote ymote changed the title Schedule Android rendering after View input and skip unused rendering work Reduce Android frame delays and remove the fling handoff pause Oct 9, 2026
ymote added 4 commits October 8, 2026 21:22
Adapt makepad#1288 (711521d) to the widgets layout in this fork. Preserve bounded dynamic-view reuse and existing back handling; omit the newer upstream cancel-scope dependency.
Adapt makepad#1296 (95e0ad5) to this fork. Preserve async eviction recovery and error reporting; omit slice-image options absent in this widget API.
@ymote ymote changed the title Reduce Android frame delays and remove the fling handoff pause Reduce Android frame delays, idle redraws, and image work Oct 9, 2026
@ymote
ymote marked this pull request as ready for review October 9, 2026 20:59
@ymote
ymote merged commit 9c79173 into main Oct 9, 2026
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