Hermes JavaScript 引擎完整教程:本地构建、字节码编译、内存排查与性能优化一次讲清
【免费下载链接】hermesA JavaScript engine optimized for running React Native.项目地址: https://gitcode.com/gh_mirrors/hermes/hermes
Hermes 是 Meta 为 React Native 打造的 JavaScript 引擎,核心能力是把 JS 代码在运行前编译成紧凑的字节码,从而缩短应用启动时间、压低常驻内存。本文会带你从零构建 Hermes 本地环境,讲清各个 CLI 工具的分工,并给出内存排查与性能分析的完整思路,适合 RN 开发者和想深入了解引擎内部的读者。
Hermes 为什么成了 React Native 的启动速度利器
传统做法下,RN 应用冷启动时要先加载 JS 源码、现场解析并编译,包体越大这一步越慢,还会额外占用内存持有源码字符串。Hermes 的做法是在发布阶段就把 JS 提前编译(AOT)成字节码文件,运行时直接执行,源码不需要随包携带。这带来三个实际收益:启动更快、内存占用更低,以及代码不会以明文源码形式出现在包里。
对只使用官方预编译产物的开发者,这套机制是透明的;但如果你要自定义构建、排查线上内存问题,或者评估引擎参数,就需要理解下面的工具链。
本地构建和运行 Hermes 最快的路径
Hermes 是一个 C++17 项目,用 CMake 加 Ninja 构建,clang、gcc 和 Visual C++ 都可以。前置依赖只需要:C++ 编译器、cmake、ninja、git、python3。默认构建不需要 ICU——大小写转换、Unicode 排序、日期格式化这些能力引擎自带;只有显式开启-DHERMES_ENABLE_INTL=ON时才需要安装 ICU。
拿到源码后,两步完成配置和编译:
git clone https://gitcode.com/gh_mirrors/hermes/hermes cmake -S hermes -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug && cmake --build ./build产物在build/bin/下,主程序hermes既能执行 JS 源码,也能当 REPL 用:
build/bin/hermes test.js更完整的依赖清单、Windows 构建方式和 test262 测试套件跑法,见 官方构建文档。
hermes、hermesc、hvm、hdb、hbcdump 五个工具各干什么
构建完成后你会得到一组职责单一的 CLI 工具,理解它们的分工是后续所有操作的基础:
- hermes:全家桶,源码编译、字节码执行、REPL 一体;
- hermesc:只做 JS 到字节码的独立编译器,不负责执行,适合接入构建流水线;
- hvm:只执行字节码的独立 VM,适合嵌入或单独测试执行阶段;
- hdb:命令行 JavaScript 调试器,支持断点、变量检查,源码位于 tools/hdb/;
- hbcdump:字节码反汇编器,把
.hbc文件还原成可读的指令序列。
编译与执行分离的设计意味着你可以把 hermesc 放进 CI 提前产出字节码,把 hvm 留给需要轻量运行时的场景。
把 JavaScript 编译成 Hermes 字节码并查看产物
编译动作本身就是一行参数的事:hermes -emit-binary -out test.hbc test.js,产出的test.hbc是纯字节码,不含原始源码。想确认编译器到底生成了什么,用hbcdump test.hbc反汇编即可,输出里能看到指令、寄存器分配和字面量布局。
整个编译管线(解析 → IR 生成 → 标量优化 → 字节码生成)由 lib/CompilerDriver/ 里的驱动程序串起来,优化器各 pass 的说明可以进一步参考 doc/Optimizer.md。对日常使用来说,知道-emit-binary这个开关和 hbcdump 这个验证手段就够用了。
Hermes 内存排查思路:读懂堆快照的 Containment 与 Retainers 视图
线上应用内存膨胀时,第一手段是导出堆快照。快照的生成逻辑在 lib/VM/HeapSnapshot.cpp,导出的文件可以直接用 Chrome DevTools 的 Memory 面板打开,阅读顺序建议如下:
先看 Containment 视图,从 GC roots 往下按 Retained Size(保留大小)排序,判断内存主要沉淀在哪一类对象上:
上图中寄存器(Registers)、IdentifierTable、CharStrings 等条目各自贡献了多少 Retained Size,一眼可辨。确定可疑类别后,切到 Retainers 视图,沿着引用链向上追"谁在持有这些对象"——Distance 表示距离根节点的引用层数,Retained Size 表示该引用链锁住的总内存:
这张图展示了一个数组元素经由 Registers 被 GC roots 持有的完整链路,是定位"某个对象为什么没被回收"的典型路径。
Hermes 性能优化:用基准数据判断解释执行还是 JIT
Hermes 提供两种执行方式:纯解释器和 JIT 编译器。JIT 会动态编译热点函数为本地代码,牺牲一点内存换取吞吐,官方在多个基准上的对比数据可以参考:
可以看到 JIT 模式下大部分基准的执行时间明显下降,但收益因工作负载而异,启动敏感型应用是否开 JIT 需要结合内存预算权衡。做局部优化时,lib/VM/Profiler/ 下的剖析器可以按函数统计执行时间、分配次数,repo里的 benchmarks/ 目录也内置了 octane、raytracer 等可直接复跑的用例。
使用 Hermes 容易踩的三个坑
- 版本要和 React Native 严格对应。每个 Hermes 版本面向特定 RN 版本,混用轻则功能异常,重则直接崩溃,升级时务必查 release 说明里的配套关系。
- Debug 构建不能代表真实性能。
-DCMAKE_BUILD_TYPE=Debug是为了方便调试,做性能对比、内存压测时请切到 Release,否则数据失真。 - 以为必须装 ICU 才能构建。只有需要完整 Intl API(
HERMES_ENABLE_INTL=ON)且平台是 Linux/Windows 时才依赖 ICU,默认构建完全不需要,Apple 和 Android 用的是平台自带的实现。
把构建流程跑通、掌握五个 CLI 工具、会用堆快照读内存、会用 profiler 定位热点,Hermes 在日常开发和问题排查中需要的能力就基本齐了。
【免费下载链接】hermesA JavaScript engine optimized for running React Native.项目地址: https://gitcode.com/gh_mirrors/hermes/hermes
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考