Batch Android animated prop updates into one JNI call per surface - #58765
Closed
bartlomiejbloniarz wants to merge 2 commits into
Closed
bartlomiejbloniarz wants to merge 2 commits into
bartlomiejbloniarz wants to merge 2 commits into
Conversation
Summary: With the batched delegate from the previous PR, 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 Test Plan: - JVM: `BatchedAnimatedPropsMountItemTest`, `MountingManagerAnimatedPropsTest`, `MatrixMathHelperTest` and `SkewMatrixHelperTest` pass. The scale regression test fails without the `TransformHelper` change. - Native: the encoder, registry and `RawProps` tests pass on Android. The numeric-color fallback test fails without the checked conversion. - The Android arm64 release build succeeds. C++ API snapshots regenerated. Not built for iOS.
…sts and scaffolding Tests and C++ API snapshots for the change in the parent commit.
bartlomiejbloniarz
added this pull request to stack #58767
September 30, 2026 13:00
|
Caution Invalid Base Branch The base branch for this PR is |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary:
With the batched delegate from the previous PR, Android applied the backend's synchronous updates with one JNI call and one
ReadableNativeMapper view per frame. WhenoptimizedAnimatedPropUpdatesis on, a surface's updates now go to the UI thread in a single call:FabricMountingManager::synchronouslyUpdateAnimatedPropsencodes them into int and double buffers, andBatchedAnimatedPropsMountItemdecodes 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
packAnimatedPropsserializer 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 producesJavaOnlyArraytransforms,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
optimizedAnimatedPropUpdatesis enabledTest Plan:
BatchedAnimatedPropsMountItemTest,MountingManagerAnimatedPropsTest,MatrixMathHelperTestandSkewMatrixHelperTestpass. The scale regression test fails without theTransformHelperchange.RawPropstests pass on Android. The numeric-color fallback test fails without the checked conversion.