facebook / react-native

A framework for building native applications using React
https://reactnative.dev
MIT License
119.24k stars 24.34k forks source link

Hermes seems to take longer to process large promises inside React Native #41631

Open AlexLablaiksSAP opened 1 year ago

AlexLablaiksSAP commented 1 year ago

Description

Hermes seems to take longer to process large promises inside React Native when compared to other JavaScript engines such as JavaScriptCore (Android) and Chakra (Windows).

I have recently reported this issue with the Hermes engine at https://github.com/facebook/hermes/issues/1024. However, after setting up a command line comparison vs React Native, it would appear that there is some configuration or integration with Hermes that is causing the slowdown to occur within React Native and not the command line. I'm not sure if this is related some of the diagnostic hooks or some metro configuration.

The issue persists in both Debug and Release, see "Steps to reproduce".

Please note, my team's concern is primarily with the Release performance, any workaround would be appreciated.

React Native Version

0.72.6

Output of npx react-native info

info Fetching system and libraries information... System: OS: Windows 10 10.0.19044 CPU: (16) x64 Intel(R) Core(TM) i9-10885H CPU @ 2.40GHz Memory: 16.42 GB / 31.75 GB Binaries: Node: version: 20.9.0 path: C:\Program Files\nodejs\node.EXE Yarn: version: 1.22.19 path: C:\Program Files (x86)\Yarn\bin\yarn.CMD npm: version: 10.1.0 path: C:\Program Files\nodejs\npm.CMD Watchman: Not Found SDKs: Android SDK: Not Found Windows SDK: AllowDevelopmentWithoutDevLicense: Enabled AllowAllTrustedApps: Enabled Versions:

Steps to reproduce

  1. Clone hermes-promise-test, following the readme there. Note: the project contains a shared git submodule for testing.
  2. Install and run for Windows or Android via yarn install and yarn react-native start (or yarn react-native run-android).
  3. Click the "Mock Data with Nested Promises" button.
  4. Choose the 10K button
  5. Click on Format to trigger the Nested promises chain, which simply changes the casing on the 10K dataset.

If you use Hermes directly, the time will be about 7x that of JavaScriptCore (Android) or Chakra (Windows).

However, if you pull the command line version hermes-promise-cli and execute it with Hermes directly, Hermes will resolve these within 600 ms or less and will outperform Chakra on the command line.

Snack, screenshot, or link to a repository

Screenshots hermes-rel javascriptcore-rel

tmikov commented 11 months ago

@cortinico the submitter indicates that the problem is in React Native, not Hermes - does it make sense to transfer it to Hermes? It is very difficult for us to investigate issues inside RN.

cortinico commented 11 months ago

Ahh I missed the linked issue. This probably belongs to React Native but I don't think we'll have capacity to investigate this one as of today

tmikov commented 11 months ago

@cortinico I suspect that we need to work together on this. As it is today, Hermes promises are just a polyfill, so they are not terribly efficient (cough cough), and frankly we don't really fully understand that code. Some complex interaction must be happening in RN, but it clearly has something to do with Hermes too.

Do we use the promise polyfill with JSC? If that is the case, it would be interesting to run an experiment with JSC in jitless mode (for example, when running on iOS hardware - not Simulator).

AlexLablaiksSAP commented 11 months ago

I asked another developer on our team to pull and run the hermes-promise-test test repository on an actual iOS device (ensuring jitless mode was activated). Here are the release mode screenshots.

JSC:

jsc

Hermes:

hermes

alexfigliolia commented 10 months ago

Hi all, I realize I'm a little late to this, but I may have an application that may make regression testing across react native versions more simple. If anyone on the RN team at meta is interested, please feel free to ping me for an invite to the repository. This app is 100% react native and doesn't use any libraries that could hide some performance related stuff in components or animations. Everything is pure react-native public api's.

https://apps.apple.com/us/app/word-clouds/id1435511292?platform=iphone

My short observations with hermes is that it is significantly slower at runtime. There's also been a regression in JS thread performance between 0.64 and 0.7x (not related to hermes). Obviously we could chalk this up to JS core, but I'm a skeptic given the extremity of recent changes in RN architecture. Anyway, I'd like to offer up my game to you guys if you'd like it to use for benchmark testing. I've swapped RN versions in and out over the last 4-5 years and there's a clear performance trend downward.

miallo commented 5 months ago

For connecting the dots:

i-xarlos commented 5 months ago

Exactly the same issue with Hermes: System: OS: Windows 10 10.0.19045 CPU: (12) x64 Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz Memory: 7.02 GB / 31.78 GB Binaries: Node: version: 20.12.1 path: C:\Program Files\nodejs\node.EXE Yarn: version: 1.22.19 path: C:\Program Files (x86)\Yarn\bin\yarn.CMD npm: version: 8.1.2 path: C:\Program Files\nodejs\npm.CMD

Dependencies for React Native Windows:

npmPackages: "@react-native-community/cli": Not Found react: installed: 18.2.0 wanted: 18.2.0 react-native: installed: 0.72.7 wanted: 0.72.7 react-native-windows: installed: 0.72.32 wanted: 0.72.32

The test was done on these different machines, exactly the same result: Hermes engine for windows takes at least twice (2X) as long to resolve promise.all, doesn't matter if it's Intel or AMD the results are the same. Using Chakra engine takes half the time in all tests.

Processor & Memory Processor: AMD Ryzen 3 7320U with Radeon Graphics Physical memory: 8 GiB

Processor & Memory Processor: AMD Ryzen 7 7736U with Radeon Graphics Physical memory: 16 GiB

Processor & Memory Processor: Intel(R) Core(TM) 7 150U Physical memory: 16 GiB