一起認識 Hermes Engine

blackbing Playground
verybuy-dev
Published in
8 min readJun 8, 2021
Hermes Engine

react-native@0.64 的升級帶來幾個重大更新,其中 Hermes Engine 終於更新了,其實早在一開始 react-native@0.60.1 時就已經支援 Android 了,我們團隊也躍躍欲試,不過當時因為不支援 Proxy Object(issue: Consider supporting Proxy #33),因次就先 pass。不過這次 0.64 的更新終於解決這個問題(Hermes with Proxy Support),而且還支援 iOS/Android,這麽誘人的更新一定不能放過。

最近終於成功升級 react-native@0.64 並且開啟了 Hermes Engine,一起重新認識 Hermes Engine 吧。

使用者體驗

對使用者來說,用戶對 App 與 Web 相比所期待的更為苛刻,一般來說,使用者會期待 App 的啟動速度更快,執行效能更好,這也是為何重度的使用者更傾向於下載 App 而不是使用 Web,因為重度的用戶往往更希望掌控權在自己手上,我想到你我就要打開,而且你要比用網站還要快,不然我為什麼要下載你這個 App?

Javascript Engine

react-native 作為開發 Mobile 主要應用場景,最為人詬病的便是多了 javascript 的啟動與執行時間,雖然 react-native 實現了使用 javascript 開發跨平台應用程式,然而執行的 javascript engine(Android: jsc, iOS: JavaScriptCore) 卻也成為了 react-native 的包袱,無法發揮原生應用程式的效能。

舉例來說,瀏覽器都以提升 Web 畫面渲染速度,CSS 處理,提升與 DOM 的交互性能為目標,並且要相容低版本的程式碼;但在 react-native 裡頭,javascript engine 只是提供了執行 javascript的功能,不需要支援低版本的 javascript 語法,也不需要支援舊語法,畫面的渲染也是交由 native 來處理,javascript Engine 只是做了一層 bridge 而已。

在低階手機中這個問題更加的明顯,所有的程式都要透過 javascript Engine 做一層轉譯之後才交由 native 來執行,雖然可行但也犧牲了效能體驗。

這也是為何 Facebook 開發團隊為了增進效能而決定重新造了一個新的 javascript Engine 的原因,react-native 非常需要一個針對 Mobile Platform 優化過的 javascript Engine。

Hermes Engine

2019 年 Facebook 開源了 Hermes Engine,帶來幾個驚艷的改善指標。

Data source: Facebook engineers
  • 程式啟動時間降低 2.29 秒
  • 程式大小下降 19 mb
  • 記憶體使用率下降 49 mb

而為何可以有這種重大的突破?主要有三個手段:

1. Bytecode precompilation

Hermes: An open source JavaScript engine optimized for mobile apps, starting with React Native

簡單的說,在 react-native 架構裡頭,原本在 run time 需要做:

Parse → Compile → Execute

但這些動作會延長啟動時間,而 Hermes Engine 將前兩項(parse, compile) 提前在 build time 就完成,讓程式在發布之前就先編譯好成 bytecode,大幅縮短程式可執行的時間。

2. No JIT(Just-In-Time)

JIT 是一種結合編譯(Compile) 與直譯(Interpret) 的手段,讓 Javascript 運行的更快。關於編譯(Compile) 與直譯(Interpret) 有興趣的同學參考以下連結有更詳細的解釋:

但 JIT 必須先預先分析程式(warm up) 才能運作,因此會拉長程式開始啟動的時間。而 Hermes Engine 不用 JIT,改採預先編譯程式,並優化直譯的效能。

3. Garbage collector strategy

設計針對 Mobile App 較為嚴苛的硬體設計的垃圾回收機制。控制記憶體的使用在中低階手機中非常重要,由於 Mobile 的記憶體有限,系統會自動清理使用過多記憶體的應用程式,當需要重新啟動時往往需要花費更多的時間,而 Hermes 的特殊垃圾回收機制,針對記憶體碎片進行整理,並把不需要的記憶體區塊還給系統,不做 javascript Heap 的掃描,進而節省了記憶體的使用。

編譯標準

既然是 Hermes 是 Javascript Engine,需要注意的是目前 Hermes 支援的語言標準是 ES6,並且選擇性的不支援某些語法,例如 with eval() 等等,更詳細的可以參考 這份文件。不過支援度已經很完整了,用起來沒有什麼大問題。

開發

上面提到 Hermes 啟用 precompilation 來提高執行程式的效率,但在 Debug 模式中不啟用 precompilation,讓開發時可以進行 hot reload。

另外開發工具也增加了許多監測 Memory, break point 的工具,與 Flipper 更深的整合等等,DX(Developer Experience) 的部分我之後會再額外寫一篇文章介紹。

需要注意的是:聽起來 Hermes Engine 好像很厲害,不過它的架構設計主要是針對 Mobile App 做優化的,browser 環境與 node 環境並不適合這種架構,開發團隊目前沒有打算要支援更多的環境。

結論 (2021/6/9 討論更新)

最後附上一些我們 Verybuy App 升級之後的觀測數據為總結:

  • iOS IPA Size: 增加2.66 Mb(增加了一些🤔)。
    (Kudo Chien: ios ipa 會變大應該是因為原本 jsc 是用系統的,不佔 ipa 的空間。)
  • Android APK Size: 降低 15.8 Mb(哇靠~這降低超多的🥰)。
    (Kudo Chien: libhermes.so 檔案真的很小,讓 v8 望塵莫及,我認為就算 v8 整合 startup snapshot 可能 TTI 也比不上 hermes,因為 libv8android.so 真的肥蠻多的)
  • TTI(Time To Interactive): iOS 降低 2.6 秒(喔哦哦~啟動時間變得更快了🤩)。
    (Kudo Chien: 一般人都只討論 TTI,不過我認為實務上還有其他需要考量的,譬如長時間佔用的 cpu / memory,或者 javascript 的效能。我發現有不少用戶使用 v8-android 在 crypto 相關的應用,上次瞄到 coinbase 好像用了 v8-android-jit,所以在不同的應用中,JIT 還是有好處的。)
VeryBuy with Hermes Engine

其實升級 react-native@0.64 踩到了一些坑,細節也是蠻多的,如果大家在升級 react-native@0.64 時有遇到問題也歡迎一起討論。我們踩過的細節之後我之後再額外寫一篇文章分享給大家(老高上身)。

參考連結:

--

--

blackbing Playground
verybuy-dev

Bingo Yang。記錄一些生活與工作的雜事,偶爾會寫一些前端網頁開發的心得,過去的足跡在 http://blog.blackbing.net