Skip to content

Commit b85a42a

Browse files
authored
Use commit hook only for React commits (#8365)
## Summary This PR introduces `USE_COMMIT_HOOK_ONLY_FOR_REACT_COMMITS` static feature flag that, when enabled, skips the `ReanimatedCommitHook` logic for commits with unknown source, including state updates. Previously, the fps would decrease by 30-50% while scrolling. After this change, the impact of scrolling is significantly smaller. The PR is somewhat similar to #7668 which was reverted in #7867 but this time we just skip applying the styles instead of influencing the pause commits mechanism. | Before | After | |:-:|:-:| | <video src="https://github.com/user-attachments/assets/bd49e918-0983-4b84-a902-caa0bb5a6f16" /> | <video src="https://github.com/user-attachments/assets/d503d129-b4af-4804-96b3-329490da0f05" /> | ## Test plan * Tested with "🚁 Performance scroll" example * Tested with "♟️ Chessboard" example (+ inside `<ScrollView>`) * Tested with "🔝 Sticky header" example
1 parent 1200238 commit b85a42a

File tree

8 files changed

+35
-4
lines changed

8 files changed

+35
-4
lines changed

apps/common-app/src/apps/reanimated/examples/AboutExample.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,16 @@ export default function AboutExample() {
103103
? 'Enabled'
104104
: 'Disabled'}
105105
</Text>
106+
<Text style={styles.text}>
107+
<Text style={styles.bold}>
108+
USE_COMMIT_HOOK_ONLY_FOR_REACT_COMMITS:
109+
</Text>{' '}
110+
{getStaticFeatureFlagReanimated(
111+
'USE_COMMIT_HOOK_ONLY_FOR_REACT_COMMITS'
112+
)
113+
? 'Enabled'
114+
: 'Disabled'}
115+
</Text>
106116
<Text style={styles.text}>
107117
<Text style={styles.bold}>IOS_DYNAMIC_FRAMERATE_ENABLED:</Text>{' '}
108118
{getStaticFeatureFlagWorklets('IOS_DYNAMIC_FRAMERATE_ENABLED')

apps/fabric-example/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
"DISABLE_COMMIT_PAUSING_MECHANISM": true,
2929
"ANDROID_SYNCHRONOUSLY_UPDATE_UI_PROPS": true,
3030
"EXPERIMENTAL_CSS_ANIMATIONS_FOR_SVG_COMPONENTS": true,
31-
"USE_SYNCHRONIZABLE_FOR_MUTABLES": true
31+
"USE_SYNCHRONIZABLE_FOR_MUTABLES": true,
32+
"USE_COMMIT_HOOK_ONLY_FOR_REACT_COMMITS": true
3233
}
3334
},
3435
"worklets": {

apps/macos-example/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@
3838
"DISABLE_COMMIT_PAUSING_MECHANISM": true,
3939
"ANDROID_SYNCHRONOUSLY_UPDATE_UI_PROPS": true,
4040
"EXPERIMENTAL_CSS_ANIMATIONS_FOR_SVG_COMPONENTS": true,
41-
"USE_SYNCHRONIZABLE_FOR_MUTABLES": true
41+
"USE_SYNCHRONIZABLE_FOR_MUTABLES": true,
42+
"USE_COMMIT_HOOK_ONLY_FOR_REACT_COMMITS": true
4243
}
4344
},
4445
"worklets": {

apps/tvos-example/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@
4747
"DISABLE_COMMIT_PAUSING_MECHANISM": true,
4848
"ANDROID_SYNCHRONOUSLY_UPDATE_UI_PROPS": true,
4949
"EXPERIMENTAL_CSS_ANIMATIONS_FOR_SVG_COMPONENTS": true,
50-
"USE_SYNCHRONIZABLE_FOR_MUTABLES": true
50+
"USE_SYNCHRONIZABLE_FOR_MUTABLES": true,
51+
"USE_COMMIT_HOOK_ONLY_FOR_REACT_COMMITS": true
5152
}
5253
},
5354
"worklets": {

docs/docs-reanimated/docs/guides/feature-flags.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Feature flags are available since Reanimated 4.
2020
| [`ANDROID_SYNCHRONOUSLY_UPDATE_UI_PROPS`](#android_synchronously_update_ui_props) | [static](#static-feature-flags) | 4.0.0 | &ndash; | `false` |
2121
| [`EXPERIMENTAL_CSS_ANIMATIONS_FOR_SVG_COMPONENTS`](#experimental_css_animations_for_svg_components) | [static](#static-feature-flags) | 4.1.0 | &ndash; | `false` |
2222
| [`USE_SYNCHRONIZABLE_FOR_MUTABLES`](#use_synchronizable_for_mutables) | [static](#static-feature-flags) | 4.1.0 | &ndash; | `false` |
23+
| [`USE_COMMIT_HOOK_ONLY_FOR_REACT_COMMITS`](#use_commit_hook_only_for_react_commits) | [static](#static-feature-flags) | 4.2.0 | &ndash; | `false` |
2324

2425
:::info
2526

@@ -142,6 +143,10 @@ When enabled, CSS animations and transitions will also work for a limited set of
142143

143144
This feature flag is supposed to speedup shared value reads on the RN runtime by reducing the number of calls to `executeOnUIRuntimeSync`. When enabled, mutables (which are the primitives behind shared values) use `Synchronizable` state to check if they should sync with the UI Runtime. For more details, see [PR #8080](https://github.com/software-mansion/react-native-reanimated/pull/8080).
144145

146+
### `USE_COMMIT_HOOK_ONLY_FOR_REACT_COMMITS`
147+
148+
This feature flag is supposed to fix performance regressions of animations while scrolling. When enabled, `ReanimatedCommitHook` applies latest animated styles and props only for React commits, which means the logic will be skipped for other commits, including state updates.
149+
145150
## Static feature flags
146151

147152
Static flags are intended to be resolved during code compilation and cannot be changed during application runtime. To enable a static feature flag, you need to:

packages/react-native-reanimated/Common/cpp/reanimated/Fabric/ReanimatedCommitHook.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <reanimated/Fabric/ReanimatedCommitHook.h>
22
#include <reanimated/Fabric/ReanimatedCommitShadowNode.h>
33
#include <reanimated/Fabric/ShadowTreeCloner.h>
4+
#include <reanimated/Tools/FeatureFlags.h>
45
#include <reanimated/Tools/ReanimatedSystraceSection.h>
56

67
#include <react/renderer/core/ComponentDescriptor.h>
@@ -73,6 +74,16 @@ RootShadowNode::Unshared ReanimatedCommitHook::shadowTreeWillCommit(
7374
return newRootShadowNode;
7475
}
7576

77+
if constexpr (StaticFeatureFlags::getFlag(
78+
"USE_COMMIT_HOOK_ONLY_FOR_REACT_COMMITS")) {
79+
// State updates are based on the currently committed ShadowTree,
80+
// which means that all animation changes are already included.
81+
// Therefore, there's no need to reapply styles from the props map.
82+
if (commitOptions.source != ShadowTreeCommitSource::React) {
83+
return newRootShadowNode;
84+
}
85+
}
86+
7687
// ShadowTree not commited by Reanimated, apply updates from the updates
7788
// registry manager
7889
reaShadowNode->unsetReanimatedMountTrait();

packages/react-native-reanimated/src/featureFlags/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ const DefaultStaticFeatureFlags = {
5757
ANDROID_SYNCHRONOUSLY_UPDATE_UI_PROPS: false,
5858
EXPERIMENTAL_CSS_ANIMATIONS_FOR_SVG_COMPONENTS: false,
5959
USE_SYNCHRONIZABLE_FOR_MUTABLES: false,
60+
USE_COMMIT_HOOK_ONLY_FOR_REACT_COMMITS: false,
6061
} as const satisfies typeof StaticFeatureFlagsJSON;
6162

6263
type StaticFeatureFlagsSchema = {

packages/react-native-reanimated/src/featureFlags/staticFlags.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
"DISABLE_COMMIT_PAUSING_MECHANISM": false,
44
"ANDROID_SYNCHRONOUSLY_UPDATE_UI_PROPS": false,
55
"EXPERIMENTAL_CSS_ANIMATIONS_FOR_SVG_COMPONENTS": false,
6-
"USE_SYNCHRONIZABLE_FOR_MUTABLES": false
6+
"USE_SYNCHRONIZABLE_FOR_MUTABLES": false,
7+
"USE_COMMIT_HOOK_ONLY_FOR_REACT_COMMITS": false
78
}

0 commit comments

Comments
 (0)