WubaRN hermes调研-基于混合工程的改造方案

WubaRN-hermes调研

Target React Native version: v0.64.0-rc.2


为推广 0.64 版本,基于 WubaRN 0.64.0-rc.2 框架版本,调研 hermes。WubaRN 0.64.x 改造过程见:WubaRN升级RN到0.64.x

内容

Hermes介绍

Facebook 在 ChainReact2019 大会上正式推出了新一代 JavaScript 执行引擎 Hermes
Hermes 是个轻量级的 JS 引擎,专门对 Android 上运行 ReactNative 进行了优化, (hermes 可执行字节码,也可以执行 js)

在分析性能数据时,Facebook 团队发现 JavaScript 引擎是影响启动性能和应用包体积的重要因素。

  1. JavaScriptCore 最初是为桌面浏览器端设计,相较于桌面端,移动端能力有太多的限制。
  2. 为了能从底层对移动端进行性能优化,Facebook 团队选择自建 JavaScript 引擎,设计了Hermes,限于 iOS AppStore 审核限制,目前仅用于 Android 平台(不能动态更新非 js 文件)。

Hermes 是如何优化的?

  1. 字节码预编译
    现代主流的 JavaScript 引擎在执行一段js代码的大概流程是:先读取源码文件,解析源代码并转换成字节码 (bytecode),最后执行。在运行时解析源码转换字节码是一种时间浪费,所以 Hermes 选择预编译的方式在编译期间生成字节码。这样做一方面避免了不必要的转换时间,另一方面多出的时间可以用来优化字节码,从而提高执行效率。

  2. 放弃 JIT
    为了加快执行效率,现在主流的 JavaScript 引擎都会使用一个 JIT 编译器在运行时通过转换成机器码的方式优化 JS 代码。Faceback 团队认为 JIT 编译器有主要俩个问题:
    (1) 要在启动时候预热,对启动时间有影响;
    (2) 会增加引擎 size 大小和运行时内存消耗。

基于这俩点对性能指标的影响,Faceback 团队决定不实现JIT编译器。这里所谓放弃 JIT,有两点需要再解释一下:
(1) 纯文本 JS 代码执行效率降低。放弃JIT,是指放弃运行时 Hermes 引擎对纯文本 JS 代码的编译优化。
(2) 对 RN 代码的动态性无影响。由于 Hermes 仍然可以执行纯文本的 JS 代码,并且可以支持动态读取bytecode,因此对 RN 的动态性并无影响。

Hermes 缺点:

  1. bytecode 文件占用size过大问题:Hermes 编译的字节码文件比纯文本js文件增大 100%
  2. 执行纯文本 js 耗时长:在客户端将纯文本 js 转换成 bytecode 之前,我们让 Hermes 加载纯文本
  3. 缓存问题:使用缓存的 Hermes 引擎加载业务代码表现非常一般,甚至某些情况下比第一次加载还要慢

改造过程

官方教程:

https://reactnative.dev/docs/hermes

官方教程非常简单,但是是纯 React Native 工程的改造流程,而没有混合工程的改造流程 (且纯 React Native 工程也一堆坑)

由于 WubaRNSDK 是混合工程,所以以下改造流程为自行摸索:

react-native init projectName --version 0.64.0-rc.2

npm install

在 node_modules 中获取 hermes 引擎的 aar:

aar 后缀改为 .zip,解压出 so 库,在 WubaRNSDK 中替换掉旧有的 libjsc.so、libc++_shared.so:

修改 ReactInstanceManager 的 JavaScriptExecutorFactory 为 HermesExecutorFactory:

ReactInstanceManagerBuilder builder = ReactInstanceManager.builder()
      .setApplication((Application) context.getApplicationContext())
      .addPackage(new MainReactPackage()) 
      .setRedBoxHandler(mExceptionHandler)
      .setUseDeveloperSupport(RNDebugSwitcher.getInstance().isDebug())
      .setInitialLifecycleState(LifecycleState.BEFORE_CREATE)
      .setJavaScriptExecutorFactory(new HermesExecutorFactory());

如果运行时出现,则是转换 Bundle 时字节码版本不对:

HermesVM: Compiling JS failed: Wrong bytecode version. Expected 76 but got 59

2021-07-21 17:27:38.881 8792-8851/com.wuba.wbrn E/WubaRN: │ WubaRN$ExceptionHandler.handleException  (WubaRN.java:526)
2021-07-21 17:27:38.881 8792-8851/com.wuba.wbrn E/WubaRN: ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
2021-07-21 17:27:38.881 8792-8851/com.wuba.wbrn E/WubaRN: │  : com.facebook.jni.UnknownCppException: Unknown
2021-07-21 17:27:38.881 8792-8851/com.wuba.wbrn E/WubaRN: │ 	at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method)
2021-07-21 17:27:38.881 8792-8851/com.wuba.wbrn E/WubaRN: │ 	at android.os.Handler.handleCallback(Handler.java:883)
2021-07-21 17:27:38.881 8792-8851/com.wuba.wbrn E/WubaRN: │ 	at android.os.Handler.dispatchMessage(Handler.java:100)
2021-07-21 17:27:38.881 8792-8851/com.wuba.wbrn E/WubaRN: │ 	at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:27)
2021-07-21 17:27:38.881 8792-8851/com.wuba.wbrn E/WubaRN: │ 	at android.os.Looper.loop(Looper.java:224)
2021-07-21 17:27:38.881 8792-8851/com.wuba.wbrn E/WubaRN: │ 	at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run(MessageQueueThreadImpl.java:226)
2021-07-21 17:27:38.881 8792-8851/com.wuba.wbrn E/WubaRN: │ 	at java.lang.Thread.run(Thread.java:919)

demo 效果 (Engine: Hermes):

再尝试一下 core bundle + buz bundle 的场景:

2021-07-21 19:52:13.407 16652-16708/com.wuba.wbrn E/unknown:ReactNative: console.error: Invariant Violation: Module AppRegistry
is not a registered callable module (calling runApplication). A frequent cause of the error is that the application entry file path is incorrect. 
This can also happen when the JS bundle is corrupt or there is an early initialization error when loading React Native., js engine: hermes, js engine: hermes, stack:
    t@66:339
    o@64:330
    anonymous@63:436
    l@63:636
    p@63:1813
    u@61:1419
    handleException@61:1941
    anonymous@82:181
    reportFatalError@4:191
    value@40:2495
    value@40:634

原因为:FE 提供的字节码 core bundle 为非 0.64.x 版本的,一定要保证 core bundle、buz bundle、转换字节码版本的一致

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值