Skip to content

Batch Android animated prop updates into one JNI call per surface - #58774

Open
bartlomiejbloniarz wants to merge 3 commits into
mainfrom
export-D122570618
Open

bartlomiejbloniarz wants to merge 3 commits into
mainfrom
export-D122570618

Conversation

@bartlomiejbloniarz

Copy link
Copy Markdown
Contributor

Summary:
With the batched delegate from the previous diff, Android applied the backend's synchronous updates with one JNI call and one ReadableNativeMap per view per frame. When optimizedAnimatedPropUpdates is on, a surface's updates now go to the UI thread in a single call: FabricMountingManager::synchronouslyUpdateAnimatedProps encodes them into int and double buffers, and BatchedAnimatedPropsMountItem decodes and applies them. This continues the encoder and mount item from #56468. Views that are not mounted yet are still queued.

A view is packed only when every prop it carries has a command. Unsupported props, null resets, platform colors, malformed values and typed props send the whole view through the existing packAnimatedProps serializer as a map instead. The commands cover the props Reanimated applies synchronously on Android, following the parity review in #56468 (comment). Angles are converted to radians in C++, and radii and translations keep their px or percent units. Because the decoder produces JavaOnlyArray transforms, TransformHelper's Kotlin conversion now applies a uniform scale to Z as well as X and Y, matching the native conversion when scale is combined with 3D rotation.

On a low-end Android phone (4× Cortex-A53) with 12 views animating opacity, UI-thread time per frame's synchronous batch dropped from about 6.5 ms to 3.4 ms.

Changelog:

[Android] [Performance] - Batch synchronous animated prop updates when optimizedAnimatedPropUpdates is enabled

Differential Revision: D122570618

Bartlomiej Bloniarz added 3 commits September 30, 2026 07:34
… animates layout

Summary:
The shared animation backend decided per surface whether a frame's animated props go through a shadow tree commit or straight to the mounted views. As soon as one view animated a layout prop, every animated view on that surface went through the commit path for the whole animation, including views that only animate `transform` or `opacity`. Besides the extra commit work, on Android this moved those views from `updatePropsSynchronously` to regular mounts. There the synchronous mount props cache (`overrideBySynchronousMountPropsAtMountingAndroid`) replaced the incoming transform with its last synchronously written value, so the view froze while the other view's layout animation ran and jumped when it ended.

The decision is now made per view. `SurfaceUpdates` holds a surface's mutations keyed by view tag, and `applySurfaceUpdates` splits them into views with layout updates, which go through `commitUpdates`, and the rest, which are applied synchronously. `AnimationMutation` and `AnimationMutations` move to `AnimationMutation.h`, still included by `AnimationBackend.h`. `AnimatedPropsRegistry::update` reads the frame's batches instead of the merged per-surface map.

## Changelog:

[General] [Fixed] - A view animating only non-layout props on the shared animation backend no longer freezes while another view on the surface animates a layout prop

Differential Revision: D122570616
Summary:
The animation backend hands its synchronous updates to the platform one view at a time. This adds `UIManager::synchronouslyUpdateAnimatedProps` and a matching `SchedulerDelegate` call that receive a whole frame's updates at once, continuing #56771. The backend uses it when `optimizedAnimatedPropUpdates` is on. The default delegate implementation forwards to the existing per-view update, so platforms that don't implement it are unaffected.

## Changelog:

[General] [Changed] - Add a batched scheduler delegate call for animated prop updates behind `optimizedAnimatedPropUpdates`

Differential Revision: D122570617
Summary:
With the batched delegate from the previous diff, Android applied the backend's synchronous updates with one JNI call and one `ReadableNativeMap` per view per frame. When `optimizedAnimatedPropUpdates` is on, a surface's updates now go to the UI thread in a single call: `FabricMountingManager::synchronouslyUpdateAnimatedProps` encodes them into int and double buffers, and `BatchedAnimatedPropsMountItem` decodes and applies them. This continues the encoder and mount item from #56468. Views that are not mounted yet are still queued.

A view is packed only when every prop it carries has a command. Unsupported props, null resets, platform colors, malformed values and typed props send the whole view through the existing `packAnimatedProps` serializer as a map instead. The commands cover the props Reanimated applies synchronously on Android, following the parity review in #56468 (comment). Angles are converted to radians in C++, and radii and translations keep their px or percent units. Because the decoder produces `JavaOnlyArray` transforms, `TransformHelper`'s Kotlin conversion now applies a uniform scale to Z as well as X and Y, matching the native conversion when scale is combined with 3D rotation.

On a low-end Android phone (4× Cortex-A53) with 12 views animating opacity, UI-thread time per frame's synchronous batch dropped from about 6.5 ms to 3.4 ms.

## Changelog:

[Android] [Performance] - Batch synchronous animated prop updates when `optimizedAnimatedPropUpdates` is enabled

Differential Revision: D122570618
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Sep 30, 2026
@facebook-github-tools facebook-github-tools Bot added p: Software Mansion Partner: Software Mansion Partner p: Facebook Partner: Facebook labels Sep 30, 2026
@meta-codesync

meta-codesync Bot commented Sep 30, 2026

Copy link
Copy Markdown

@bartlomiejbloniarz has exported this pull request. If you are a Meta employee, you can view the originating Diff in D122570618.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. meta-exported p: Facebook Partner: Facebook p: Software Mansion Partner: Software Mansion Partner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant