Since Google’s release of Flutter, Facebook has been working on iterations of React-Native to optimize its performance and avoid being outperformed by Flutter. One of the big recent moves is to open source a JavaScript engine and include it in React-Native. So what’s different about this engine, and what’s better than V8 and JSC JavaScript engines?

1. What is the Hermes engine and what are its advantages?

First things first: The Hermes engine is a JavaScript engine developed by Facebook to replace JavaScript Core on the React-Native Android side. The Hermes engine has the advantage of being a lightweight JavaScript engine for mobile devices. Aot compilation reduces memory usage on Android devices, reduces installation package size, and improves execution efficiency.

What is a JavaScript engine?

A JavaScript engine is a virtual machine that specializes in JavaScript scripting and is typically shipped with a web browser.

3. Mainstream JavaScript engines

V8 (Google), JavaScriptCore (Apple), And SpiderMonkey (Firefox)

4. JavaScript engine in RN

Weex, Android: V8, iOS: JavaScriptCore

RN, Android: JavaScriptCore (Hermes, V8), iOS: JavaScriptCore (Apple required)

Note: Hermes Engine is supported with react-Native 0.60.2 release

5. The character of Hermes

  • Precompiled bytecode (the engine loads binaries more efficiently than it runs JS scripts)

  • No JIT compiler (reduced engine size, optimized memory footprint, but worse performance than V8 and JSC running JS scripts directly)

  • Garbage collection strategy for mobile

6. Optimization principle

Snippets from code.fb.com


Traditional JavaScript engines typically perform code execution in the pattern shown above, with Babel escape and Minify compression in the compile phase, production as JavaScript scripts, and interpreting and executing tasks that need to be done at runtime (e.g. V8 engines, It also compiles JavaScript to native machine code at run time.) The obvious disadvantage is that it needs to be interpreted and executed at run time, and even takes up system resources to perform compilation tasks.


Snippets from code.fb.com


The Hermes engine uses AOT compilation to advance the interpretation and compilation process to the compilation stage, and only performs machine code execution at runtime, greatly increasing operational efficiency.

7. Existing projects are connected to Hermes

  • Upgrade React-Native and related libraries (low cost)

  • Since react-Native 0.60.x is changed to rely on AndroidX, the Android project needs to use version 28 or higher to compile, adapt to higher Android versions, and need to migrate to AndroidX (high cost).

  • Modify build.gradle to add Hermes properties and dependencies (less cost)

8. Is CodePush supported?

The pre-compiled Hermes engine generates the index.android.bundle file in assets folder in the same way as RN. RN’s index.android.bundle is a compressed JavaScript script file, while Hermes is a binary file precompiled. CodePush can continue to be used because only the product file format difference does not change the loading method of the original JS Bundle.


Currently, two code-push release modes are supported:


Release way Whether to support note
code-push release-react
Supported, but cannot produce precompiled script artifacts
You need to rely on the react-native bundle command to package scripts. This command does not support precompilation
code-push release
support

9. Debugging efficiency

In Debug mode, Hermes does not enable precompilation to support Hot Reload. The disadvantage is that in Release mode, all advantages of The Hermes engine are lost, and even the performance of the original engine is worse because there is no JIT. But developer mode is not about performance, it’s about debugging efficiency.


Debug mode with built-in libherm-inspector. So, Chrome Inspect, DevTools, better than the original RN debugging experience (in-app agent, can’t Debug native calls synchronously)

10.ES standard support

Hermes supports ES6, keeping up with the latest JavaScript specifications. To optimize engine size, lesser-used language features in RN programs, such as native eval(), are not supported.

11. Performance research

Package size analysis


JSC engine Release package


Hermes engine Release package


Original package size 20MB (JSC)
New package size 18MB (Hermes)

The package size is reduced by 2MB for an overall reduction of 2MB / 20MB = 10%

Analyzing the reasons for the reduction of package size, it can be found that only the size of lib and assets are different between package contents.




JSC engine Release package


Hermes engine Release package


Comparing the lib content, it is found that the size difference is mainly caused by the difference between libjsc.so and libherm.so, i.e. the size of the Hermes engine.


JSC engine Release package


Hermes engine Release package


Comparing assets content, it is found that the size change is mainly caused by index.Android. bundle, which is JavaScript packaging product, while in Hermes mode, it is more caused by further compilation into binary code.


The combination of the two effects results in overall reduction and package size optimization. (The more platforms supported, the better the package volume optimization effect)

Memory Analysis

Experimental method: The Memory Profiler is used to view the Memory usage in the same stable state of the business page


JSC engine Release package


Hermes engine Release package


The average memory usage of the original package is 210MB
The average memory footprint of a new package is 190MB


The memory usage is reduced by more than 20MB on average, and the overall memory usage is reduced by 10% (20MB / 210MB)
Analysis of Profiler data shows that memory optimization occurs primarily in the Code memory area.


JSC engine Release package


Hermes engine Release package


The description of the memory Code area in the Official Google documentation:
Code: The memory your application uses to process Code and resources such as dex bytecodes, optimized or compiled dex codes,.so libraries, and fonts.


Considering the reduction in the size of libherm.so from the package size analysis in the previous section, it is easy to imagine that the memory footprint is reduced because of the reduction in the footprint of.so. The other two have a slightly different, but negligible, footprint on JavaScript memory.


▍ TTI performance

TTI: Time to Interactive. It is the Time between the start of the page and the completion of the page rendering and the normal response to the user’s input. It is a measure of user experience on the mobile terminal.

In React-Native Android, it is mainly the time from the start of Application onCreate to the completion of RN component rendering for interaction.

It is worth teasing that the iOS version of Pref Monitor directly includes the display of this indicator, but the Android version of Pref Monitor only has four indicators and does not have TTI indicators.

On The Android platform, you can obtain the native component corresponding to RN through the ReactFindViewUtil class provided by RN, register the corresponding render callback, and record the TTI end time when the control rendering is complete.




JSC engine Release package


Hermes engine Release package


The original package TTI 829 ms

A new package TTI 694 ms

TTI decreased by 135ms, and overall decreased by 135ms / 829ms = 16%

12. To summarize

In the face of the offensive of Flutter, React-Native finally made some changes. Hermes does have performance advantages as a JavaScript engine suitable for mobile applications. I hope this article will give you a better understanding of Hermes.

This article is first sent from Pratt & Whitney Travel Product Technology (ID: PZCXtech)