写点什么

RN 技术探索:Hermes Engine 初探

  • 2019-09-19
  • 本文字数:2415 字

    阅读完需:约 8 分钟

RN 技术探索:Hermes Engine 初探

自从 Google 的 Flutter 发布之后,Facebook 对 React-Native 的迭代开始快了起来,优化 React-Native 的性能表现,避免被 Flutter 比下去。最近一个比较大的动作是开源了一个 JavaScript 引擎,并将其包含到 React-Native 中。那么这款引擎它有什么不同,相比 V8、JSC 这些 JavaScript 引擎又有什么优势呢,现在本文来为你揭晓。

1.Hermes 引擎是什么,优势有哪些?

重要的事情提前说:Hermes 引擎是 Facebook 研发,在 React-Native Android 端用于替换 JavaScript Core 的 JavaScript 引擎。Hermes 引擎的优势是适合移动端的轻量级 JavaScript 引擎,使用 aot 编译,可以减少 Android 端内存使用,减小安装包大小,提升执行效率。

2.什么是 JavaScript 引擎?

JavaScript 引擎是一个专门处理 JavaScript 脚本的虚拟机,一般会附带在网页浏览器之中。

3.主流 JavaScript 引擎

V8(Google)、JavaScriptCore(Apple)、SpiderMonkey(Firefox)

4.RN 中的 JavaScript 引擎

  • Weex,Android:V8,iOS:JavaScriptCore

  • RN,Android:JavaScriptCore(Hermes、V8),iOS:JavaScriptCore(Apple 要求)


注:Hermes Engine 在 React-native 0.60.2 版本后支持

5.Hermes 的特色

  • 预编译字节码(引擎加载二进制代码效率高于运行 JS 脚本)

  • 无 JIT 编译器(减小了引擎大小,优化内存占用,但直接运行 JS 脚本的性能差于 V8 和 JSC)

  • 针对移动端的垃圾回收策略

6.优化原理


截取自 code.fb.com


传统 JavaScript 引擎通常是以上图的模式完成代码执行的,编译阶段只完成 babel 转义和 minify 压缩,产物还是 JavaScript 脚本,解释与执行的任务都需要在运行时完成(如 V8 引擎,还会在运行时将 JavaScript 编译为本地机器码)很明显缺点就是在运行时需要边解释边执行,甚至需要占用系统资源执行编译任务。



截取自 code.fb.com


Hermes 引擎使用了 aot 编译的方式,将解释和编译过程前置到编译阶段,运行时只完成机器码的执行,大大提高了运行效率。

7.已有项目接入 Hermes

  • 升级 React-Native 及相关库升级(成本较小)

  • 因为 React-Native 0.60.x 变更为依赖 AndroidX,所以 Android 项目需要使用 28 以上版本编译,适配 Android 高版本,且需要迁移到 AndroidX(成本较大)

  • 修改 build.gradle,添加 Hermes 相关属性及依赖(成本较小)

8.是否支持 CodePush?

Hermes 引擎预编译后的产物与 RN 原方式相同,都是在 assets 文件夹下生成的 index.android.bundle 文件。RN 原方式中 index.android.bundle 是经过压缩的 JavaScript 脚本文件,Hermes 预编译后则是二进制文件。因为只有产物文件格式的区别,并没有修改原有 JS Bundle 的加载方式,所以 CodePush 可以继续使用。


目前 code-push 的两种发布模式支持情况:


9.调试效率

Debug 模式下 Hermes 不开启预编译以支持 Hot Reload ,缺点是 Release 模式下所有 Hermes 引擎优势都不存在,甚至因为无 JIT 导致性能还要差于原有引擎。但开发者模式并不追求性能,而更追求调试效率。


Debug 模式内置 libhermes-inspector.so ,支持 Chrome inspect 的使用,支持 DevTools 协议,比原有 RN 调试体验更佳(应用内代理,不能同步调试原生调用)

10.ES 标准支持

Hermes 支持 ES6,紧跟最新的 JavaScript 规范。为了优化引擎大小,不支持 RN 程序中使用较少的语言特性,如本地 eval()。

11.性能调研

包大小分析


JSC 引擎 Release 包



Hermes 引擎 Release 包


原包大小 20MB(JSC)


新包大小 18MB(Hermes)


包大小减小 2MB,整体减少 2MB / 20MB = 10%


分析具体包大小减小的原因可以发现,包内容两者只有 lib 大小和 assets 的大小存在差异。



JSC 引擎 Release 包



Hermes 引擎 Release 包


对比 lib 内容,发现大小差距主要是由 libjsc.solibhermes.so 两者的差距导致的,即 Hermes 引擎的大小。



JSC 引擎 Release 包



Hermes 引擎 Release 包


对比 assets 内容,发现大小变化主要由 index.android.bundle ,即 JavaScript 打包产物引起,Hermes 模式下反而更大的原因是进一步编译为二进制代码。


两者影响叠加导致整体减小,包大小得到优化。(支持的平台越多,包体积优化效果越好)

内存分析

实验方法:在相同的业务页面稳定状态下通过 Memory Profiler 查看内存占用情况



JSC 引擎 Release 包



Hermes 引擎 Release 包


原包平均内存占用 210MB


新包平均内存占用 190MB


内存占用平均减小 20MB 以上,整体减小 20MB / 210MB = 10%


分析 Profiler 数据可以发现,内存优化主要发生在 Code 内存区。



JSC 引擎 Release 包



Hermes 引擎 Release 包


Google 官方文档中对内存 Code 区的描述:


Code:您的应用用于处理代码和资源(如 dex 字节码、已优化或已编译的 dex 码、.so 库和字体)的内存。


联系到上个章节中包大小分析中 libhermes.so 尺寸的减小,可以很容易想到,内存占用的减少就是因为 .so 对内存占用的减小。另外两者对 JavaScript 内存的占用也有细微差别,但是可以忽略不计。

TTI 性能

TTI:Time to Interactive,用户可交互时间,启动到页面渲染完成并且可以正常响应用户的输入的时间,衡量用户体验的移动端指标。


React-Native Android 中主要是 Application onCreate 开始到 RN 组件渲染完成可交互的时间。


值得吐槽的是,在 iOS 版本的 Pref Monitor 中直接就包含了这个指标的显示,但是 Android 版本的 Pref Monitor 只有四个指标,且并没有 TTI 这一指标。


在 Android 平台上可以通过 RN 提供的 ReactFindViewUtil 类获取 RN 组件对应的原生组件,注册对应的渲染回调,在控件渲染完成时记录 TTI 结束时间。



JSC 引擎 Release 包



Hermes 引擎 Release 包


原包 TTI 829ms


新包 TTI 694ms


TTI 减少 135ms,整体减少 135ms / 829ms = 16%

12.总结

面对 Flutter 的咄咄攻势,React-Native 终于做出了一些改变,Hermes 作为一款适合移动端的 JavaScript 引擎,确实有其性能优势,希望通过本文能够让你更加了解 Hermes。


本文转载自公众号滴滴技术(ID:didi_tech)。


原文链接:


https://mp.weixin.qq.com/s/Di8rbkXfcojrazQ3FQNkRg


2019-09-19 15:282262

评论

发布
暂无评论
发现更多内容

ABAP 和 Java 里的单例模式攻击

汪子熙

Java abap 1月月更

实时渲染大赛太卷了!来看大佬提前交卷的优秀参赛作品

3DCAT实时渲染

3D 实时渲染

Hive SQL底层执行过程 | 社区征文

五分钟学大数据

hive 新春征文

知名身份安全厂商九州云腾加入龙蜥社区

OpenAnolis小助手

Linux 开源 互联网

记线上服务 cpu 爆表 问题解决

常清静

性能优化 压测分析 CPU问题

记 服务 内存飙升压测 - 分析总结

常清静

压测分析 内存问题 排查工具

【架构师训练营】模块六作业

樰巳-堕~Horry

架构实战营 「架构实战营」

一文聊透Netty核心引擎Reactor的运转架构

bin的技术小屋

网络编程 nio 中间件 jdk8 netty

夜莺系统调研报告

苍狼

AI贺新年,开发者的虎年这样过才有意思

华为云开发者联盟

AI 华为云

对GO切片的理解

CRMEB

区块链赋能民生“第一单”:200多套房源试水,“链宜租”租房系统上线

CECBC

模块 6 作业

miliving

MyBatis3源码解析(1)探索准备

Java mybatis

回顾明道云的2021(文末互动有奖)

明道云

你必须知道的Java17新特性-密封类(Sealed Classes)

蜜糖的代码注释

Java 开发 后端开发

🏆【Alibaba微服务技术系列】「Dubbo3.0技术专题」(1)Dubbo3新特性概览的介绍说明

洛神灬殇

dubbo Dubbo3 Alibaba技术 1月日更 Apache alibaba

openLooKeng1.5.0新版本正式上线

openLooKeng

架构实战营 - 群讨论汇总 (2022)

华仔

#架构实战营

开发postgreSQL connector支持update/delete操作的代码

openLooKeng

Python Qt GUI设计:做一款串口调试助手(实战篇—1)

不脱发的程序猿

PyQt Python Qt Python Qt GUI设计 串口调试助手

详解 Flink CEP(以直播平台监控用户弹幕为例)

五分钟学大数据

flink 1月月更

11张图深入理解分布式锁原理

慕枫技术笔记

微服务 后端 1月月更

(1-23/23)Transformer依然很强

mtfelix

300天创作 2022Y300P

如何优雅地解决平台字体适应问题

编程三昧

CSS 前端开发 HTML5, CSS3 1月月更

Go 语言快速入门指南:Go 函数

宇宙之一粟

函数 Go 语言 1月月更

架构训练营 week7 作业

红莲疾风

「架构实战营」

参加开源贡献后,大厂向我抛出了橄榄枝

openLooKeng

Spark 核心详解

五分钟学大数据

spark 1月月更

ReactNative进阶(三十七):应用 SectionList 实现分组列表

No Silver Bullet

1月月更 ReactNative sectionList

AI+遥感:释放每个像元价值

百度大脑

人工智能 AI

RN 技术探索:Hermes Engine 初探_架构_王李坤_InfoQ精选文章