RN 技術探索:Hermes Engine 初探

滴滴技術 發表於 2022-12-06

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.最佳化原理


RN 技術探索:Hermes Engine 初探擷取自code.fb.com
傳統 JavaScript 引擎通常是以上圖的模式完成程式碼執行的,編譯階段只完成 babel 轉義和 minify 壓縮,產物還是 JavaScript 指令碼,解釋與執行的任務都需要在執行時完成(如 V8 引擎,還會在執行時將 JavaScript 編譯為本地機器碼)很明顯缺點就是在執行時需要邊解釋邊執行,甚至需要佔用系統資源執行編譯任務。
RN 技術探索:Hermes Engine 初探
擷取自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 的兩種釋出模式支援情況:
釋出方式是否支援備註
code-push release-react
支援,但無法產生預編譯指令碼產物
需依賴react-native bundle命令完成指令碼打包,該命令尚不支援預編譯
code-push release
支援

9.除錯效率

Debug 模式下 Hermes 不開啟預編譯以支援 Hot Reload ,缺點是 Release 模式下所有Hermes 引擎優勢都不存在,甚至因為無 JIT 導致效能還要差於原有引擎。但開發者模式並不追求效能,而更追求除錯效率。

Debug 模式內建 libhermes-inspector.so ,支援 Chrome inspect 的使用,支援 DevTools 協議,比原有 RN 除錯體驗更佳(應用內代理,不能同步除錯原生呼叫)

10.ES 標準支援

Hermes 支援 ES6,緊跟最新的 JavaScript 規範。為了最佳化引擎大小,不支援 RN 程式中使用較少的語言特性,如本地 eval()。

11.效能調研

包大小分析

RN 技術探索:Hermes Engine 初探
JSC 引擎 Release 包
RN 技術探索:Hermes Engine 初探
Hermes 引擎 Release 包
原包大小 20MB(JSC)
新包大小 18MB(Hermes)
包大小減小 2MB,整體減少 2MB / 20MB = 10%
分析具體包大小減小的原因可以發現,包內容兩者只有 lib 大小和 assets 的大小存在差異。
RN 技術探索:Hermes Engine 初探
JSC 引擎 Release 包
RN 技術探索:Hermes Engine 初探
Hermes 引擎 Release 包
對比 lib 內容,發現大小差距主要是由 libjsc.so 和 libhermes.so 兩者的差距導致的,即 Hermes 引擎的大小。
RN 技術探索:Hermes Engine 初探
JSC 引擎 Release 包
RN 技術探索:Hermes Engine 初探
Hermes 引擎 Release 包
對比 assets 內容,發現大小變化主要由 index.android.bundle ,即 JavaScript 打包產物引起,Hermes 模式下反而更大的原因是進一步編譯為二進位制程式碼。
兩者影響疊加導致整體減小,包大小得到最佳化。(支援的平臺越多,包體積最佳化效果越好)

記憶體分析

實驗方法:在相同的業務頁面穩定狀態下透過 Memory Profiler 檢視記憶體佔用情況
RN 技術探索:Hermes Engine 初探
JSC 引擎 Release 包
RN 技術探索:Hermes Engine 初探
Hermes 引擎 Release 包
原包平均記憶體佔用 210MB
新包平均記憶體佔用 190MB
記憶體佔用平均減小20MB以上,整體減小20MB / 210MB = 10%
分析 Profiler 資料可以發現,記憶體最佳化主要發生在 Code 記憶體區。
RN 技術探索:Hermes Engine 初探
JSC 引擎 Release 包
RN 技術探索:Hermes Engine 初探
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結束時間。

RN 技術探索:Hermes Engine 初探
JSC 引擎 Release 包

RN 技術探索:Hermes Engine 初探
Hermes 引擎 Release 包
原包 TTI 829ms
新包 TTI 694ms
TTI 減少 135ms,整體減少 135ms / 829ms = 16%

12.總結

面對 Flutter 的咄咄攻勢,React-Native 終於做出了一些改變,Hermes 作為一款適合移動端的 JavaScript 引擎,確實有其效能優勢,希望透過本文能夠讓你更加了解 Hermes。
本文首發自普惠出行產品技術 (ID:pzcxtech)
本文作者
RN 技術探索:Hermes Engine 初探
王李坤
滴滴 | 高階軟體開發工程師    哲學程式設計師,是個氣管炎、偽學霸,主要研究移動端技術,目前負責終端技術的落地。相信“技術能夠改變世界”,喜歡學習新技術

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69908606/viewspace-2653574/,如需轉載,請註明出處,否則將追究法律責任。