重要的事情提早說:Hermes引擎是Facebook研發,在React-Native Android端用於替換JavaScript Core的JavaScript引擎。Hermes引擎的優點是適合移動端的輕量級JavaScript引擎,使用aot編譯,能夠減小Android端內存使用,減少安裝包大小,提高執行效率。react
JavaScript引擎是一個專門處理JavaScript腳本的虛擬機,通常會附帶在網頁瀏覽器之中。android
V8(Google)、JavaScriptCore(Apple)、SpiderMonkey(Firefox)react-native
Weex,Android:V8,iOS:JavaScriptCore瀏覽器
RN,Android:JavaScriptCore(Hermes、V8),iOS:JavaScriptCore(Apple要求)babel
注:Hermes Engine在React-native 0.60.2 版本後支持ide
(截取自code.fb.com)性能
傳統JavaScript引擎一般是以上圖的模式完成代碼執行的,編譯階段只完成babel轉義和minify壓縮,產物仍是JavaScript腳本,解釋與執行的任務都須要在運行時完成(如V8引擎,還會在運行時將JavaScript編譯爲本地機器碼)很明顯缺點就是在運行時須要邊解釋邊執行,甚至須要佔用系統資源執行編譯任務。字體
(截取自code.fb.com)gradle
Hermes引擎使用了aot編譯的方式,將解釋和編譯過程前置到編譯階段,運行時只完成機器碼的執行,大大提升了運行效率。優化
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 | 支持 |
Debug模式下Hermes不開啓預編譯以支持Hot Reload,缺點是Release模式下全部Hermes引擎優點都不存在,甚至由於無JIT致使性能還要差於原有引擎。但開發者模式並不追求性能,而更追求調試效率。
Debug模式內置libhermes-inspector.so,支持Chrome inspect的使用,支持DevTools協議,比原有RN調試體驗更佳(應用內代理,不能同步調試原生調用)
Hermes支持ES6,緊跟最新的JavaScript規範。爲了優化引擎大小,不支持RN程序中使用較少的語言特性,如本地eval()。
(JSC引擎Release包)
(Hermes引擎Release包)
原包大小20MB(JSC)
新包大小18MB(Hermes)
包大小減少2MB,總體減小2MB / 20MB = 10%
分析具體包大小減少的緣由能夠發現,包內容二者只有lib大小和assets的大小存在差別。
(JSC引擎Release包)
(Hermes引擎Release包)
對比lib內容,發現大小差距主要是由libjsc.so和libhermes.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: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%
面對Flutter的咄咄攻勢,React-Native終於作出了一些改變,Hermes做爲一款適合移動端的JavaScript引擎,確實有其性能優點,但願經過本文可以讓你更加了解Hermes。