Skip to content

perf: Drive Android CSS platform transitions from a single frame pump - #10126

Closed
MatiPl01 wants to merge 5 commits into
@matipl01/android-css-opacity-transitionsfrom
@matipl01/android-css-frame-pump-engine
Closed

MatiPl01 wants to merge 5 commits into
@matipl01/android-css-opacity-transitionsfrom
@matipl01/android-css-frame-pump-engine

Conversation

@MatiPl01

@MatiPl01 MatiPl01 commented Aug 3, 2026 •

Copy link
Copy Markdown
Contributor

Replaces the per-view ObjectAnimator engine behind Android platform CSS transitions with a single Choreographer frame callback that drives all running transitions, and batches the JS-to-UI command stream into one main-looper message per burst instead of one per transition.

ObjectAnimator fought CSS semantics in six places (delay, pre-start value writes, seek-before-start, isRunning quirks, duration scale, end-listener identity). Computing each frame from an absolute start timestamp handles delay, late starts and interruption resume directly, so all of those workarounds go away. This also stops ObjectAnimator from strongly holding views (API 35+) and removes per-frame allocations in the commit-repair pass.

Measured on an API 36 emulator (hardware GL, debug build, dev JS): 504 views with opacity transitions, 4 scenarios, median frame time in ms and frames drawn per 30s, mean of 3 runs. Each run used a freshly booted emulator with a checksum-verified install, and every measurement window was bracketed by health probes to reject degraded runs.

scenario plain loop sync UI props ObjectAnimator engine frame pump
churn, 20 re-renders/sec 81.0 / 651 30.3 / 1724 24.3 / 1788 23.3 / 1799
churn, 5 re-renders/sec 81.0 / 655 30.7 / 1715 24.7 / 1789 22.0 / 1793
pulse, all views every 2s 27.7 / 728 22.7 / 762 17.0 / 611 17.0 / 656
stagger, 0-500ms delays 33.3 / 995 24.3 / 1032 20.7 / 994 18.3 / 1011

Jank under churn: 0.1-0.8% (pump) vs 4.4-4.6% (sync UI props). Pulse and stagger show similar frame counts for all engines because few views animate at any moment, so nothing is pressured into dropping frames; the differences there are in frame time.

@coderabbitai

coderabbitai Bot commented Aug 3, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (3)
  • main
  • ^[0-9]+.[0-9]+-stable
  • ^worklets-[0-9]+.[0-9]+-stable

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 4991a43e-bab5-48db-a710-389d9020f7e7

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@MatiPl01 MatiPl01 self-assigned this Aug 3, 2026
@MatiPl01

Copy link
Copy Markdown
Contributor Author

Superseded by #10170, which rebuilds the frame pump on top of the mount-gated repair (#10168) and the interned JNI ids (#10169). Device measurements for the final stack are in the benchmark report.

@MatiPl01 MatiPl01 closed this Aug 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant