东亚银行、岚图汽车带你解锁 AIGC 时代的数字化人才培养各赛道新模式! 了解详情
写点什么

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:282006

评论

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

为何数据类大项目都会先做盘点??

奔向架构师

数据仓库 数据治理 9月日更

科技的进步会造福人类吗--闲聊科幻

姬翔

9月日更

深入理解Java虚拟机-虚拟机执行子系统,字节跳动超高难度三面java程序员面经

Java 程序员 后端

性能测试中集合点和多阶段问题初探

FunTester

性能测试 接口测试 测试框架 测试开发 FunTester

Kubernetes环境Traefik部署与应用

Galen Suen

Kubernetes Helm Traefik

linux之chsh命令

入门小站

Linux

【LeetCode】有效的括号字符串Java题解

Albert

算法 LeetCode 9月日更

Golang 中的好代码 VS 烂代码

baiyutang

编码 Go 语言 9月日更

Vue进阶(幺零八):npm run build 错误 (node:7852) UnhandledPromiseRejectionWarning: CssSyntaxError:xxxx. 解决分析

No Silver Bullet

Vue 9月日更

OpenSL ES

Changing Lin

9月日更

三分钟带你入门-redis-高可用架构之哨兵,大厂Java高级面试题汇总解答

Java 程序员 后端

HTML进阶(三)

Augus

html 9月日更

常用特殊符号大全

入门小站

工具

写给互联网工程师的5G书 | 0. 前言

俞凡

架构 5G

深入理解Java中的不可变对象(1),面试加分项

Java 程序员 后端

深入理解JAVA虚拟机原理之垃圾回收器机制(一),Java开发6年了

Java 程序员 后端

Mybatis Plus 的 @SqlParser 的说明与替代注解

玄兴梦影

注解 过滤器 Mybatis-Plus

【Flutter 专题】49 图解 Flutter 与 Android 原生交互

阿策小和尚

Flutter 小菜 0 基础学习 Flutter Android 小菜鸟 9月日更

一名优秀的技术Leader是如何炼成的?

架构精进之路

管理 技术管理 引航计划 内容合集

Parted 创建 GPT 分区

耳东@Erdong

Linux 9月日更 parted 磁盘分区

Redis核心原理与实践--列表实现原理之ziplist结构

binecy

redis 源码分析

双指针算法之同向双指针

泽睿

Java 数据结构 面试 双指针算法

网络攻防学习笔记 Day133

穿过生命散发芬芳

网络基础 9月日更

分享 4 个前端开发必备的 Chrome 扩展

devpoint

SVG chrome扩展 9月日更

写给互联网工程师的5G书 | 1. 简介

俞凡

架构 5G

深入理解Java中的不可变对象,这可能是目前最全的

Java 程序员 后端

数据结构和算法应用

Albert

算法 9月日更

手撸二叉树之二叉搜索树中的众数

HelloWorld杰少

9月日更

Context 和 struct

Rayjun

struct Context Go 语言

服务注册与发现的原理和实现

万俊峰Kevin

微服务 服务注册与发现 microservice 服务发现 Go 语言

深入理解 Java 多线程核心知识:跳槽面试必备,Java算法基础面试题

Java 程序员 后端

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