

桔妹导读:自从 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 端内存使用,减小安装包大小,提升执行效率。
JavaScript 引擎是一个专门处理 JavaScript 脚本的虚拟机,一般会附带在网页浏览器之中。
V8(Google)、JavaScriptCore(Apple)、SpiderMonkey(Firefox)
Weex,Android:V8,iOS:JavaScriptCore
RN,Android:JavaScriptCore(Hermes、V8),iOS:JavaScriptCore(Apple 要求)
注:Hermes Engine在React-native 0.60.2 版本后支持
预编译字节码(引擎加载二进制代码效率高于运行JS脚本)
无 JIT 编译器(减小了引擎大小,优化内存占用,但直接运行 JS 脚本的性能差于 V8 和 JSC)
针对移动端的垃圾回收策略
截取自code.fb.com传统 JavaScript 引擎通常是以上图的模式完成代码执行的,编译阶段只完成 babel 转义和 minify 压缩,产物还是 JavaScript 脚本,解释与执行的任务都需要在运行时完成(如 V8 引擎,还会在运行时将 JavaScript 编译为本地机器码)很明显缺点就是在运行时需要边解释边执行,甚至需要占用系统资源执行编译任务。
截取自code.fb.comHermes 引擎使用了 aot 编译的方式,将解释和编译过程前置到编译阶段,运行时只完成机器码的执行,大大提高了运行效率。升级 React-Native 及相关库升级(成本较小)
因为 React-Native 0.60.x 变更为依赖 AndroidX,所以 Android 项目需要使用 28 以上版本编译,适配 Android 高版本,且需要迁移到 AndroidX(成本较大)
修改 build.gradle,添加 Hermes 相关属性及依赖(成本较小)
| 发布方式 | 是否支持 | 备注 |
| code-push release-react | 支持,但无法产生预编译脚本产物 | 需依赖react-native bundle命令完成脚本打包,该命令尚不支持预编译 |
| code-push release | 支持 |
JSC 引擎 Release 包
Hermes 引擎 Release 包原包大小 20MB(JSC)新包大小 18MB(Hermes)包大小减小 2MB,整体减少 2MB / 20MB = 10%分析具体包大小减小的原因可以发现,包内容两者只有 lib 大小和 assets 的大小存在差异。
JSC 引擎 Release 包
Hermes 引擎 Release 包对比 lib 内容,发现大小差距主要是由 libjsc.so 和 libhermes.so 两者的差距导致的,即 Hermes 引擎的大小。
JSC 引擎 Release 包
Hermes 引擎 Release 包对比 assets 内容,发现大小变化主要由 index.android.bundle ,即 JavaScript 打包产物引起,Hermes 模式下反而更大的原因是进一步编译为二进制代码。两者影响叠加导致整体减小,包大小得到优化。(支持的平台越多,包体积优化效果越好)
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 内存的占用也有细微差别,但是可以忽略不计。
JSC 引擎 Release 包
Hermes 引擎 Release 包原包 TTI 829ms新包 TTI 694msTTI 减少 135ms,整体减少 135ms / 829ms = 16%本文作者
▬王李坤滴滴 | 高级软件开发工程师 哲学程序员,是个气管炎、伪学霸,主要研究移动端技术,目前负责终端技术的落地。相信“技术能够改变世界”,喜欢学习新技术