-
Notifications
You must be signed in to change notification settings - Fork 24.8k
Description
Description
Hello, this is Tomasz from the Reanimated team at Software Mansion. We're getting numerous issue reports from our library users who complain about poor performance of our library on Android when the New Architecture is enabled. Most of the app developers state that performance used to be better on the Legacy Architecture so we consider this to be a regression of enabling the New Architecture in their apps.
During our investigation, we found out that one of the bottlenecks is rooted in the Fabric implementation itself. Reanimated uses the exact same way to update view props and styles as React Native does. Reanimated commits all changes by calling ShadowTree::commit
method in C++ (on the UI thread) and relies on the rest of the New Architecture rendering pipeline, including the mounting manager.
To demonstrate the behavior, I prepared a simple reproducer without react-native-reanimated that simply uses React state and React renders to update the rotation of 400 views. While I understand that there are no easily explainable use cases for updating the rotation of 400 views at once (which takes ~300 ms in a debug mode), based on this we can calculate how long it takes to mount updates for a single view (almost a 1 ms, or ~0.75 ms to be exact). Considering that nowadays most of smartphones run at 60 or even 120 fps and there's only 8 ms to render each animation frame, this means we can update only up to 10 views during a single animation frame which is far below reasonable expectations.

I've also measured how long it takes to update only {opacity}
(~90 ms), {transform:[{rotate}],[{scale}]}
(~400 ms) and {opacity,transform:[{rotate}]}
(~350 ms).
When it comes to transforms, keep in mind that rotation is stored inside a single key-value pair object inside a single-item array so most likely this type of data structure takes more time to be serialized (especially if JNI calls are involved). This however still doesn't explain why it takes 0.2 ms in the debug mode to update only the opacity of a single view.

Just for comparison, I've also run some measurements in the release (profileable) build. It looks like mounting is ~2x faster than in debug mode. Keep in mind though, that most of the developers use a debug build to develop their app and implement animations so can't really advise them to "just use a release build".

Steps to reproduce
- Install the dependencies with
yarn install
- Open the application with Android Studio with
open -a "Android Studio" android
- Build the application in the debug mode and launch it on a low-end Android device, e.g. OPPO A16
- Open "Profiler" tab in Android Studio
- Select "Capture System Activities / System Trace"
- Press "Start anyway" button in Android Studio to start recording
- Press "Set rotation" button several times in the reproducer app
- Press "Stop recording and show results"
- Scroll down to "m.reproducerapp" row and click on the label
- Zoom in to the traces from a single rotation update using WASD keys
- Hover over "IntBufferBatchMountItem::mountInstructions::UPDATE_PROPS numInstructions=400"
- See the running time, e.g. "Running: 337.16 ms"
React Native Version
0.79.3
Affected Platforms
Runtime - Android
Areas
Fabric - The New Renderer
Output of npx @react-native-community/cli info
System:
OS: macOS 15.5
CPU: (12) arm64 Apple M3 Pro
Memory: 109.67 MB / 18.00 GB
Shell:
version: "5.9"
path: /bin/zsh
Binaries:
Node:
version: 18.19.0
path: ~/.nvm/versions/node/v18.19.0/bin/node
Yarn:
version: 3.6.4
path: ~/.nvm/versions/node/v18.19.0/bin/yarn
npm:
version: 10.2.3
path: ~/.nvm/versions/node/v18.19.0/bin/npm
Watchman:
version: 2025.05.26.00
path: /opt/homebrew/bin/watchman
Managers:
CocoaPods:
version: 1.16.2
path: /Users/tomekzaw/.rbenv/shims/pod
SDKs:
iOS SDK:
Platforms:
- DriverKit 24.5
- iOS 18.5
- macOS 15.5
- tvOS 18.5
- visionOS 2.5
- watchOS 11.5
Android SDK:
API Levels:
- "30"
- "31"
- "33"
- "34"
- "35"
Build Tools:
- 30.0.2
- 30.0.3
- 31.0.0
- 33.0.0
- 33.0.1
- 34.0.0
- 35.0.0
System Images:
- android-33 | Google APIs ARM 64 v8a
- android-34 | Google APIs ARM 64 v8a
- android-35 | Google Play ARM 64 v8a
- android-36 | Google APIs ARM 64 v8a
Android NDK: Not Found
IDEs:
Android Studio: 2024.3 AI-243.26053.27.2432.13536105
Xcode:
version: 16.4/16F6
path: /usr/bin/xcodebuild
Languages:
Java:
version: 17.0.15
path: /usr/bin/javac
Ruby:
version: 3.2.2
path: /Users/tomekzaw/.rbenv/shims/ruby
npmPackages:
"@react-native-community/cli":
installed: 18.0.0
wanted: 18.0.0
react:
installed: 19.0.0
wanted: 19.0.0
react-native:
installed: 0.79.3
wanted: 0.79.3
react-native-macos: Not Found
npmGlobalPackages:
"*react-native*": Not Found
Android:
hermesEnabled: true
newArchEnabled: true
iOS:
hermesEnabled: Not found
newArchEnabled: false
Stacktrace or Logs
No stacktrace
MANDATORY Reproducer
https://github.com/tomekzaw/reproducer-android-slow-mounting
Screenshots and Videos
No response