Skip to content

Patch reanimated to avoid using executeOnUIRuntimeSync #6774

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from

Conversation

janicduplessis
Copy link
Contributor

@janicduplessis janicduplessis commented Jul 25, 2025

Fixes APP-####

What changed (plus any additional context for devs)

This avoids usage of executeOnUIRuntimeSync in reanimated if the shared value has not changed yet. When an animated view is mounted, on first render, reanimated queries the value of the shared value on JS thread synchronously, but for 90% of the cases that value still has its initial value since it was created at the same time as the view. If that is the case we can avoid the expensive call and return initial value directly. Whenever the shared value changes the first time we call into JS to set the dirty flag to true and then if the shared value is connected to a view again it will fall back to slow path calling executeOnUIRuntimeSync.

On low end android this is by far the slowest thing in JS traces, since it need to lock JS thread to wait for a probably already very busy UI thread.

Edit:

Perf is a lot better after upgrading RN because of a fix in hermes facebook/hermes#1572.

Screen recordings / screenshots

Before:

0.74

image

0.79

image

After:

0.74

image

0.79

image

What to test

Test everything and look for broken animations.

@janicduplessis janicduplessis marked this pull request as ready for review July 25, 2025 01:38
@jinchung
Copy link
Member

Launch in simulator or device for adae1e0

@janicduplessis janicduplessis force-pushed the @janic/reanimated-perf branch 2 times, most recently from c0add7f to a3bb128 Compare July 25, 2025 16:55
@jinchung
Copy link
Member

Launch in simulator or device for 8ec1547

@christianbaroni
Copy link
Member

I tested the build and it’s a noticeable improvement. Didn’t test everything, but I didn't see any issues where shared values are used most heavily.

This does create a small race window, right? In theory at least, where the setIsDirty invocation may have been scheduled via runOnJS, but hasn't yet run on the JS thread. If so, would be good to try to break it to understand exactly how and where that can manifest — for instance creating a shared value via useSharedValue and then before the first render completes, changing its value (via runOnUI, executeOnUIRuntimeSync) before it's read from the JS thread by useAnimatedStyle or useDerivedValue. May not happen in practice and if it does I imagine in most cases it would self correct.

@janicduplessis
Copy link
Contributor Author

This does create a small race window, right?

Yes I think in theory it is possible, but in practice I am hoping it is not (unless using executeOnUIRuntimeSync). Good idea, let me see if I can break it.

@jinchung
Copy link
Member

Launch in simulator or device for 95325ed

@jinchung
Copy link
Member

Launch in simulator or device for 3bb546b

@janicduplessis janicduplessis force-pushed the @janic/reanimated-perf branch from 561cabb to 2b3a375 Compare July 26, 2025 02:54
@jinchung
Copy link
Member

Launch in simulator or device for f028ddf

@jinchung
Copy link
Member

Launch in simulator or device for 5f2cfb8

@jinchung
Copy link
Member

Launch in simulator or device for ec1fd08

@janicduplessis janicduplessis force-pushed the @janic/reanimated-perf branch from 02e857b to c6505a8 Compare July 26, 2025 19:23
@janicduplessis
Copy link
Contributor Author

janicduplessis commented Jul 26, 2025

Been working with the reanimated team and got a version working without the possibility of race condition, using a new Synchronized value type (basically a value that can be accessed across runtimes with a lock). software-mansion/react-native-reanimated#7913, I've updated the patch to an adapted version of it that works on reanimated v3.

@jinchung
Copy link
Member

Launch in simulator or device for 4cb902d

@WoLewicki
Copy link
Contributor

After looking at the code and reading through the discussion with Reanimated team, I think there are some points to it.

  • according to the discussion in reanimated repo, there still might be cases where values go out of sync, and it can be very non-deterministic, which might make it harder to reproduce/debug
  • It is quite a big improvement and I saw executeOnUIRuntimeSync taking much time e.g. when opening Swap modal.
  • At the same time, with 0.79, this issue is not visible that much

I think in the end it's a matter of do we prefer better performance over being sure that we won't see random visual glitches. I think we can give it to QA team, and if they don't spot anything wrong after thoroughly testing it, I'd give it a go.

@janicduplessis
Copy link
Contributor Author

I think with this current version the possible issue is so unlikely to happen that the perf improvement is worth it. I tried to create an artificial case that trigger the issue and wasn't able to.

I will fix the conflict then I think we're good to go with this.

Copy link
Contributor

@WoLewicki WoLewicki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving but let's keep potential issues in mind with this one!

@janicduplessis janicduplessis force-pushed the @janic/reanimated-perf branch from c6505a8 to ba46330 Compare August 13, 2025 01:56
@jinchung
Copy link
Member

Launch in simulator or device for ff95cd7

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants