Kudo / react-native-v8

Opt-in V8 runtime for React Native Android
MIT License
926 stars 69 forks source link

[0.71][Android] Native method performance are slow #179

Open jhen0409 opened 1 year ago

jhen0409 commented 1 year ago

Hi @Kudo, I've found some issue on RNV8, it is very likely that there is a performance issue on the native bridge.

I've write a demo project here, basically it runs 10 times of native call and do simple loop in native module, it shows some notable differences in Hermes vs RNV8:

Hermes enabled

LOG  Call to test took 227.46980799734592 milliseconds.
LOG  Call to test took 120.60123699903488 milliseconds.
LOG  Call to test took 108.04817698895931 milliseconds.
LOG  Call to test took 107.52172900736332 milliseconds.
LOG  Call to test took 109.05973300337791 milliseconds.
LOG  Call to test took 108.41910800337791 milliseconds.
LOG  Call to test took 107.26053899526596 milliseconds.
LOG  Call to test took 109.81799300014973 milliseconds.
LOG  Call to test took 106.16292299330235 milliseconds.
LOG  Call to test took 108.38789799809456 milliseconds.

RNV8 enabled

LOG  Call to test took 267 milliseconds.
LOG  Call to test took 151 milliseconds.
LOG  Call to test took 145 milliseconds.
LOG  Call to test took 145 milliseconds.
LOG  Call to test took 144 milliseconds.
LOG  Call to test took 151 milliseconds.
LOG  Call to test took 145 milliseconds.
LOG  Call to test took 144 milliseconds.
LOG  Call to test took 146 milliseconds.
LOG  Call to test took 147 milliseconds.

send + iteration (70 ~ 80ms on native side) + resolve with 20000 length size ReadableArray.

It's ~80ms vs ~40ms on Release mode.

I found this problem on my project, it caused 20ms ~ 100ms delay on each native bridge call.

Also, I've found it have the same issue with JSC, not sure if this issue can be improved here.

jhen0409 commented 1 year ago

Result of Turbo Native Module (Debug mode)

Hermes:

 LOG  Call to test took 154.2415769994259 milliseconds. (native: 109ms)
 LOG  Call to test took 111.8033449947834 milliseconds. (native: 68ms)
 LOG  Call to test took 109.039754986763 milliseconds. (native: 66ms)
 LOG  Call to test took 105.16988199949265 milliseconds. (native: 65ms)
 LOG  Call to test took 96.47904500365257 milliseconds. (native: 64ms)
 LOG  Call to test took 94.72220900654793 milliseconds. (native: 64ms)
 LOG  Call to test took 87.90507000684738 milliseconds. (native: 63ms)
 LOG  Call to test took 81.62443000078201 milliseconds. (native: 64ms)
 LOG  Call to test took 87.84830698370934 milliseconds. (native: 64ms)
 LOG  Call to test took 94.18151798844337 milliseconds. (native: 64ms)

RNV8:

 LOG  Call to test took 248 milliseconds. (native: 109ms)
 LOG  Call to test took 153 milliseconds. (native: 77ms)
 LOG  Call to test took 129 milliseconds. (native: 73ms)
 LOG  Call to test took 121 milliseconds. (native: 65ms)
 LOG  Call to test took 125 milliseconds. (native: 73ms)
 LOG  Call to test took 122 milliseconds. (native: 69ms)
 LOG  Call to test took 116 milliseconds. (native: 70ms)
 LOG  Call to test took 117 milliseconds. (native: 64ms)
 LOG  Call to test took 119 milliseconds. (native: 69ms)
 LOG  Call to test took 119 milliseconds. (native: 69ms)

Ref: new-arch-test branch

Kudo commented 1 year ago

hi @jhen0409, thanks for the issue with great repro example. originally i thought this was a regression issue of v8-android-jit@11.110.3, but after downgrading to previous v8, the performance is almost the same.

after far as i can tell, it comes from the loop calls: https://github.com/jhen0409/rnv8-issue-179/blob/071f0b053c3f151ac5c9b9a4253ff4e0ec9b6f79/android/app/src/main/java/com/testv8nativebridge/TestModule.java#L33-L35. it might not be a v8 issue but my implementation inside react-native-v8. i tried to remove locks but still not as good as hermes. i'll keep investigate if i could find something to improve.