1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        V8、JSCore、Hermes、QuickJS,hybrid開(kāi)發(fā)JS引擎怎么選

        共 12542字,需瀏覽 26分鐘

         ·

        2021-03-05 14:12

        ??

        如果你喜歡我寫(xiě)的文章,可以把我的公眾號(hào)設(shè)為星標(biāo) ??,這樣每次有更新就可以及時(shí)推送給你啦


        在一般的移動(dòng)端開(kāi)發(fā)場(chǎng)景中,每次更新應(yīng)用功能都是通過(guò) Native 語(yǔ)言開(kāi)發(fā)并通過(guò)應(yīng)用市場(chǎng)版本分發(fā)來(lái)實(shí)現(xiàn)的。

        但是市場(chǎng)瞬息萬(wàn)變,Native 語(yǔ)言在開(kāi)發(fā)效率上存在一定不足,并且從 APP 版本更新應(yīng)用市場(chǎng)審核發(fā)布 再到 用戶(hù)下載更新,總會(huì)存在一定的時(shí)間差,這樣就導(dǎo)致新的功能無(wú)法及時(shí)覆蓋全量用戶(hù)。

        為了解決這個(gè)問(wèn)題,開(kāi)發(fā)者們一般會(huì)在項(xiàng)目里引入一門(mén)腳本語(yǔ)言,提速 APP 的研發(fā)流程。

        在移動(dòng)端應(yīng)用比較廣泛的腳本語(yǔ)言有 Lua 和 JavaScript,前者在游戲領(lǐng)域用的比較多,后者在應(yīng)用領(lǐng)域用的比較多。本篇文章主要是想探討一下移動(dòng)雙端(iOS & Android)的 JavaScript 引擎選型。由于個(gè)人水平有限,文章總會(huì)有遺漏和不足的地方,還請(qǐng)各位大佬多多指教。

        JS 引擎選型要點(diǎn)

        JavaScript 作為世界上最熱門(mén)的腳本語(yǔ)言,有著非常多的引擎實(shí)現(xiàn):有 Apple 御用的 JavaScriptCore,有性能最強(qiáng)勁的 V8,還有最近熱度很高的 QuickJS......如何從這些 JS 引擎里選出最適合的?我個(gè)人認(rèn)為要有幾個(gè)考量:

        • 性能:這個(gè)沒(méi)話(huà)說(shuō),肯定是越快越好
        • 體積:JS 引擎會(huì)增加一定的包體積
        • 內(nèi)存占用:內(nèi)存占用越少越好
        • JavaScript 語(yǔ)法支持程度:支持的新語(yǔ)法越多越好
        • 調(diào)試的便捷性:是否直接支持 debug?還是需要自己編譯實(shí)現(xiàn)調(diào)試工具鏈
        • 應(yīng)用市場(chǎng)平臺(tái)規(guī)范:主要是 iOS 平臺(tái),平臺(tái)禁止應(yīng)用集成帶 JIT 功能的虛擬機(jī)

        比較麻煩的是,上面的幾個(gè)點(diǎn)都不是互相獨(dú)立的:

        比如說(shuō)開(kāi)啟 JIT 的 V8 引擎,性能肯定是最好的,但它引擎體積就很大,內(nèi)存占用也很高;在包體積上很占優(yōu)勢(shì)的 QuickJS,由于沒(méi)有 JIT 加持,和有 JIT 的引擎比起來(lái)平均會(huì)有 5-10 倍的性能差距。

        下面我會(huì)綜合剛剛提到的幾個(gè)點(diǎn),并選擇了 JavaScriptCoreV8,HermesQuickJS 這 4 個(gè) JSVM,說(shuō)說(shuō)它們的優(yōu)點(diǎn)和特點(diǎn),再談?wù)勊麄兊牟蛔恪?/p>

        JS 引擎功能大比拼

        1.JavaScriptCore

        mobile_JSVM_JSC

        JavaScriptCore 是 WebKit 默認(rèn)的內(nèi)嵌 JS 引擎,wikipedia 上都沒(méi)有獨(dú)立的詞條,只在 WebKit 詞條的三級(jí)目錄[1]里介紹了一下,個(gè)人感覺(jué)還是有些不像話(huà),畢竟也是老牌 JS 引擎了。

        由于 WebKit 是 Apple 率先開(kāi)源的,所以 WebKit 引擎運(yùn)用在 Apple 自家的 Safari 瀏覽器和 WebView 上,尤其是 iOS 系統(tǒng)上,因?yàn)?Apple 的限制,所有的網(wǎng)頁(yè)只能用 WebKit 加載,所以 WebKit 在 iOS 上達(dá)到了事實(shí)壟斷,作為 WebKit 模塊一部分的 JSC,順著政策春風(fēng),也「基本」壟斷了 iOS 平臺(tái)的 JS 引擎份額。

        壟斷歸壟斷,其實(shí) JSC 的性能還是可以的。

        很多人不知道 JSC 的 JIT 功能其實(shí)比 V8 還要早,放在十幾年前是最好的 JS 引擎,只不過(guò)后來(lái)被 V8 追了上來(lái)。而且 JSC 有個(gè)重大利好,在 iOS7 之后,JSC 作為一個(gè)系統(tǒng)級(jí)的 Framework 開(kāi)放給開(kāi)發(fā)者使用,也就是說(shuō),如果你的 APP 使用 JSC,只需要在項(xiàng)目里 import 一下,包體積是 0 開(kāi)銷(xiāo)的!這點(diǎn)在今天討論的 JS 引擎中,JSC 是最能打的。


        雖然開(kāi)啟 JIT 的 JSC 性能很好,但是只限于蘋(píng)果御用的 Safari 瀏覽器和 WKWebView,只有這兩個(gè)地方 JIT 功能才是默認(rèn)開(kāi)啟的,如果在項(xiàng)目里直接引入 JSC,JIT 功能是關(guān)閉的。為什么這么做呢?RednaxelaFX 大佬[2] 給出過(guò)非常專(zhuān)業(yè)的解釋[3]

        ??

        JIT 編譯需要底層系統(tǒng)支持動(dòng)態(tài)代碼生成,對(duì)操作系統(tǒng)來(lái)說(shuō)這意味著要支持動(dòng)態(tài)分配帶有“可寫(xiě)可執(zhí)行”權(quán)限的內(nèi)存頁(yè)。當(dāng)一個(gè)應(yīng)用程序擁有請(qǐng)求分配可寫(xiě)可執(zhí)行內(nèi)存頁(yè)的權(quán)限時(shí),它會(huì)比較容易受到攻擊從而允許任意代碼動(dòng)態(tài)生成并執(zhí)行,這樣就讓惡意代碼更容易有機(jī)可乘。

        Apple 出于安全上的考慮,禁止了第三方 APP 使用 JSC 時(shí)開(kāi)啟 JIT,這些特點(diǎn)在 React Native 的 JS Runtime 頁(yè)面[4]也有過(guò)相關(guān)的解釋。不過(guò)在實(shí)際應(yīng)用中,不做重 CPU 的運(yùn)算只當(dāng)膠水語(yǔ)言使用,JSC 還是綽綽有余了。


        上面的討論都是針對(duì) iOS 系統(tǒng)的,在 Android 系統(tǒng)上,JSC 的表現(xiàn)就不盡人意了。

        JSC 并沒(méi)有對(duì) Android 機(jī)型做很好的適配,雖然可以開(kāi)啟 JIT,但是性能表現(xiàn)并不好,這也是 Facebook 決心制作 Hermes 的一個(gè)原因,具體的性能對(duì)比分析可見(jiàn)本文的 Hermes 小節(jié)。


        最后再說(shuō)說(shuō) JSC 的調(diào)試支持情況。如果是 iOS 平臺(tái),我們可以直接用 Safari 的 debbuger 功能調(diào)試,如果是 Android 平臺(tái),目前我還沒(méi)有找到一個(gè)很好的真機(jī)調(diào)試方法。


        綜合來(lái)看,JavaScriptCore 在 iOS 平臺(tái)上有非常明顯的主場(chǎng)優(yōu)勢(shì),各個(gè)指標(biāo)都是很優(yōu)秀的,但在 Android 上因?yàn)槿狈?yōu)化,表現(xiàn)并不是很好。

        2.V8

        mobile_JSVM_V8

        V8,我想我不用過(guò)多解釋了,JavaScript 能有如今的地位,V8 功不可沒(méi)。性能沒(méi)得說(shuō),開(kāi)啟 JIT 后就是業(yè)內(nèi)最強(qiáng)(不止是 JS),有很多介紹 V8 的文章,我這里就不多描述了,我們這里說(shuō)說(shuō) V8 在移動(dòng)端的表現(xiàn)。


        同樣作為 Google 家的產(chǎn)品,每一臺(tái) Android 手機(jī)上都安裝了基于 Chromium 的 WebView,V8 也一并捆綁了。但是 V8 和 Chromium 捆綁的太緊密了,不像 iOS 上的 JavaScriptCore 封裝為系統(tǒng)庫(kù)可以被所有 App 調(diào)用。這就導(dǎo)致你想在 Android 上用 V8 還得自己封裝,社區(qū)比較出名的項(xiàng)目是 J2V8[5],提供了 V8 的 Java bindings 案例。

        V8 性能沒(méi)得說(shuō),Android 上可以開(kāi)啟 JIT,但這些優(yōu)勢(shì)都是有代價(jià)的:開(kāi)啟 JIT 后內(nèi)存占用高,并且 V8 的包體積也不小(大概 7 MB 左右),如果作為只是畫(huà) UI 的 Hybrid 系統(tǒng),還是有些奢侈了。

        我們?cè)僬f(shuō)說(shuō) V8 在 iOS 上的集成。

        V8 在 2019 年推出了 JIT-less V8[6],也就是關(guān)閉 JIT 只使用 Ignition interpreter 解釋執(zhí)行 JS 文件,那么我們?cè)?iOS 上集成 V8 就成了可能,因?yàn)?Apple 還是支持接入只有解釋器功能的虛擬機(jī)引擎的。但是個(gè)人認(rèn)為關(guān)閉了 JIT 的 V8 接入 iOS 價(jià)值不大,因?yàn)橹婚_(kāi)啟解釋器的話(huà),這時(shí)候的 V8 和 JSC 的性能其實(shí)是差不多的,引入反而會(huì)增加一定的體積開(kāi)銷(xiāo)。


        V8 還有一個(gè)有意思的特性很少人提及,那就是——堆快照(Heap snapshots),這個(gè)是 V8 在 2015[7] 年就支持的功能,但是社區(qū)里很少有人討論它。

        堆快照是什么原理呢?一般來(lái)說(shuō) JSVM 啟動(dòng)后,第一步往往是解析 JS 文件,這個(gè)還是比較耗時(shí)的,V8 支持預(yù)先生成 Heap snapshots,然后直接加載到堆內(nèi)存中,快速的獲得 JS 的初始化上下文??缙脚_(tái)框架 NativeScript[8] 就利用了這樣的技術(shù),可以讓 JS 的加載速度提升 3 倍,技術(shù)細(xì)節(jié)可以看他們的博文[9]。

        V8_heap_snapshots

        V8 真機(jī)調(diào)試也需要引入第三方庫(kù),Android 端社區(qū)上有人對(duì) J2V8 做了 Chrome 調(diào)試協(xié)議的擴(kuò)展,即 J2V8-Debugger[10] 項(xiàng)目,iOS 我沒(méi)有找到相關(guān)的項(xiàng)目,可能需要自己實(shí)現(xiàn)一套擴(kuò)展。


        綜合來(lái)看 V8 的確是 JSVM 中的性能王者,Android 端使用時(shí)可以完全發(fā)揮它的威力,但是 iOS 平臺(tái)因?yàn)橹鲌?chǎng)劣勢(shì),并不是很推薦。

        3.Hermes

        mobile_JSVM_hermes

        Hermes 是 FaceBook 2019 年中旬開(kāi)源的一款 JS 引擎,從 release[11] 記錄可以看出,這個(gè)是專(zhuān)為 React Native 打造的 JS 引擎,可以說(shuō)從設(shè)計(jì)之初就是為 Hybrid UI 系統(tǒng)打造。

        Hermes 一開(kāi)始推出就是要替代原來(lái) RN Android 端的 JS 引擎,即 JavaScriptCore(因?yàn)?JSC 在 Android 端表現(xiàn)太拉垮了)。我們可以理一下時(shí)間線,F(xiàn)aceBook 自從 2019-07-12 宣布 Hermes 開(kāi)源[12]后,jsc-android[13] 的維護(hù)信息就永遠(yuǎn)的停在了 2019-06-25[14],這個(gè)信號(hào)暗示得非常的明顯:JavaScriptCore Android 我們不再維護(hù)啦,大家都去用我們做的 Hermes 啊。

        最近 Hermes 已經(jīng)計(jì)劃伴隨 React Native 0.64 版本登錄 iOS 平臺(tái)了,但是 RN 版本更新 blog 還沒(méi)有出,大家可以看看我之前對(duì) Apple 開(kāi)發(fā)者協(xié)議的解讀:Apple Agreement 3.3.2 規(guī)范解讀,在這里我就不多說(shuō)了。


        Hermes 的特點(diǎn)主要是兩個(gè),一個(gè)是不支持 JIT,一個(gè)是支持直接生成/加載字節(jié)碼,我們?cè)谙旅娣珠_(kāi)講一下。

        Hermes 不支持 JIT 的主要原因有兩個(gè):加入 JIT 后,JS 引擎啟動(dòng)的預(yù)熱時(shí)間會(huì)變長(zhǎng),一定程度上會(huì)加長(zhǎng)首屏 TTI[15](頁(yè)面首次加載可交互時(shí)間),現(xiàn)在的前端頁(yè)面都講究一個(gè)秒開(kāi),TTI 還是個(gè)挺重要的測(cè)量指標(biāo)。另一個(gè)問(wèn)題上 JIT 會(huì)增加包體積和內(nèi)存占用,Chrome 內(nèi)存占用高 V8 還是要承擔(dān)一定責(zé)任的。

        因?yàn)椴恢С?JIT,Hermes 在一些 CPU 密集計(jì)算的領(lǐng)域就不占優(yōu)勢(shì)了,所以在 Hybrid 系統(tǒng)里,最優(yōu)的解決方案就是充分發(fā)揮 JavaScript 膠水語(yǔ)言的作用,CPU 密集的計(jì)算(例如矩陣變換,參數(shù)加密等)放在 Native 里做,算好了再傳遞給 JS 表現(xiàn)在 UI 上,這樣可以兼顧性能和開(kāi)發(fā)效率。


        Hermes 最引人矚目的就是支持生成字節(jié)碼了,我在之前的博文《?? 跨端框架的核心技術(shù)到底是什么?》也提到過(guò),Hermes 加入 AOT 后,Babel、Minify、ParseCompile 這些流程全部都在開(kāi)發(fā)者電腦上完成,直接下發(fā)字節(jié)碼讓 Hermes 運(yùn)行就行,我們直接用個(gè) demo 演示一下。

        Hermes

        先寫(xiě)個(gè) test.js 的文件,里面隨便寫(xiě)點(diǎn)啥都行;然后編譯一下 Hermes 的源碼,編譯過(guò)程直接按文檔[16]來(lái)就行,我這里就略過(guò)了。

        首先 Hermes 支持直接解釋運(yùn)行 JS 代碼,就是正常的 JS 加載編譯運(yùn)行流程。

        hermes test.js

        我們可以加入 -emit-binary 參數(shù)嘗試一下生成 Bytecode 的功能:

        hermes -emit-binary -out test.hbc test.js

        然后就會(huì)生成一份 test.hbc 字節(jié)碼文件:

        hermes_bytecode

        最后我們可以讓 Hermes 直接加載運(yùn)行 test.hbc 文件:

        hermes test.hbc

        客觀評(píng)價(jià)一下 Hermes 的字節(jié)碼,首先省去了在 JS 引擎里解析編譯的流程,JS 代碼的加載速度將會(huì)大大加快,體現(xiàn)在 UI 上就是 TTI 時(shí)間會(huì)明顯縮短;另一個(gè)優(yōu)勢(shì) Hermes 的字節(jié)碼在設(shè)計(jì)時(shí)就考慮了移動(dòng)端的性能限制,支持增量加載而不是全量加載,對(duì)內(nèi)存受限的中低端 Android 機(jī)更友好;不過(guò)字節(jié)碼的體積會(huì)比原來(lái)的 JS 文件會(huì)大一些,但是考慮到 Hermes 引擎本身體積就不大,綜合考慮下來(lái)這些體積增量還是可以接受的。


        關(guān)于詳細(xì)的 Hermes 性能測(cè)試情況,網(wǎng)上有兩篇文章寫(xiě)的比較好:一篇是 React Native Memory profiling: JSC vs V8 vs Hermes[17],可以看到在 Android 設(shè)備上 Hermes 的表現(xiàn)還是很優(yōu)異的,而 JSC 的表現(xiàn)非常拉垮:

        JSCvsV8vsHermes

        另一篇是攜程的文章:攜程對(duì) RN 新一代 JS 引擎 Hermes 的調(diào)研,可以看出 Hermes 綜合成績(jī)最高(JSC 還是一樣的拉垮):

        JSVM_CPU_Performance

        說(shuō)完性能我們?cè)僬f(shuō)說(shuō) Hermes 的 JS 語(yǔ)法支持情況。

        Hermes 主要支持的是 ES6 語(yǔ)法,剛開(kāi)源時(shí)不支持 Proxy,不過(guò) v0.7.0[18] 已經(jīng)支持了。他們的團(tuán)隊(duì)也比較有想法,不支持 with eval() 等這種屬于設(shè)計(jì)糟粕的 API,這種設(shè)計(jì)的權(quán)衡我個(gè)人還是比較認(rèn)同的。


        最后我們談?wù)?Hermes 的調(diào)試功能。

        目前 Hermes 已經(jīng)支持了 Chrome 的調(diào)試協(xié)議,我們可以直接用 Chrome 的 debugging 工具直接調(diào)試 Hermes 引擎,具體的操作可見(jiàn)文檔:Debugging JS on Hermes using Google Chrome's DevTools[19]


        綜合來(lái)看,Hermes 是一款專(zhuān)為移動(dòng)端 Hybrid UI System 打造的 JS 引擎,如果要自建一套 Hybrid 系統(tǒng),Hermes 是一個(gè)非常好的選擇。

        4.QuickJS

        mobile_JSVM_quickjs

        正式介紹 QuickJS 前我們先說(shuō)說(shuō)它的作者:Fabrice Bellard。

        軟件界一直有個(gè)說(shuō)法,一個(gè)高級(jí)程序員創(chuàng)造的價(jià)值可以超過(guò) 20 個(gè)平庸的程序員,但 Fabrice Bellard 不是高級(jí)程序員,他是天才,在我看來(lái)他的創(chuàng)造力可以超過(guò) 20 個(gè)高級(jí)程序員,我們可以順著時(shí)間軸[20]理一下他創(chuàng)造過(guò)些什么:

        ??
        • 1997年,發(fā)布了最快速的計(jì)算圓周率的算法,此算法是 Bailey-Borwein-Plouffe 公式的變體,前者的時(shí)間復(fù)雜度是O(n^3),他給優(yōu)化成了O(n^2),使得計(jì)算速度提高了43%,這是他在數(shù)學(xué)上的成就
        • 2000 年,發(fā)布了 FFmpeg,這是他在音視頻領(lǐng)域的一個(gè)成就
        • 2000,2001,2018 三年三度獲得國(guó)際混淆 C 代碼大賽
        • 2002 年,發(fā)布了TinyGL,這是他在圖形學(xué)領(lǐng)域的成就
        • 2005 年,發(fā)布了 QEMU,這是他在虛擬化領(lǐng)域的成就
        • 2011 年,他用 JavaScript 寫(xiě)了一個(gè) PC 虛擬機(jī) Jslinux,一個(gè)跑在瀏覽器上的 Linux 操作系統(tǒng)
        • 2019 年,發(fā)布了 QuickJS,一個(gè)支持 ES2020 規(guī)范的 JS 虛擬機(jī)

        當(dāng)人和人之間的差距差了幾個(gè)數(shù)量級(jí)后,羨慕嫉妒之類(lèi)的情緒就會(huì)轉(zhuǎn)變?yōu)槌绨萘?,Bellard 就是一個(gè)這樣的人。


        收復(fù)一下心情,我們來(lái)看一下 QuickJS 這個(gè)項(xiàng)目。QuickJS 繼承了 Fabrice Bellard 作品的一貫特色——小巧而又強(qiáng)大。

        QuickJS 體積非常小,只有幾個(gè) C 文件,沒(méi)有亂七八糟的第三方依賴(lài)。但是他的功能又非常完善,JS 語(yǔ)法支持ES2020[21],Test262[22] 的測(cè)試顯示,QuickJS 的語(yǔ)法支持度比 V8 還要高。

        test262

        那么 QuickJS 的性能如何呢?QuickJS 官上有個(gè)基準(zhǔn)測(cè)試[23],綜合比較了多款 JS 引擎對(duì)同一測(cè)試用例的跑分情況。下面是測(cè)試結(jié)果:

        JSVM_Benchmark

        結(jié)合上面的表格和個(gè)人的一些測(cè)試,可以簡(jiǎn)單的得出一些結(jié)論:

        • 開(kāi)啟 JIT 的 V8 綜合評(píng)分差不多是 QuickJS 的 35 倍,但是在同等主打輕量的 JS 引擎中,QuickJS 的性能還是很耀眼的
        • 在內(nèi)存占用上,QuickJS 遠(yuǎn)低于 V8,畢竟 JIT 是是吃?xún)?nèi)存的大戶(hù),而且 QuickJS 的設(shè)計(jì)對(duì)嵌入式系統(tǒng)很友好(Bellard 成就獎(jiǎng)杯 ?? 再 +1)
        • QuickJS 和 Hermes 的跑分情況是差不多的,我私下做了一些性能測(cè)試,這兩個(gè)引擎的表現(xiàn)也很相近

        因?yàn)?QuickJS 的設(shè)計(jì),我不經(jīng)好奇他和 Lua 的性能對(duì)比如何。

        Lua 是一門(mén)非常小巧精悍的語(yǔ)言,在游戲領(lǐng)域和 C/C++ 開(kāi)發(fā)中一直充當(dāng)膠水語(yǔ)言的作用。

        我個(gè)人寫(xiě)了一些測(cè)試用例,發(fā)現(xiàn) QuickJS 和 Lua 的執(zhí)行效率也是差不多的,后來(lái)在網(wǎng)上找到一篇博文 Lua vs QuickJS[24],這個(gè)老哥也做了一些測(cè)試,結(jié)論也是它倆的性能差不多,在部分場(chǎng)景 Lua 會(huì)比 QuickJS 快一些。


        官方文檔里有提到,QuickJS 支持生成字節(jié)碼[25],這樣可以免去 JS 文件編譯解析的過(guò)程。

        我一開(kāi)始以為 QuickJS 和 Hermes 一樣,可以直接生成字節(jié)碼,然后交給 QuickJS 解釋執(zhí)行。后來(lái)自己編譯了一下才發(fā)現(xiàn),QuickJS 的作用機(jī)制和 Hermes 還不太一樣:qjsc 生成字節(jié)碼的 -e-c 選項(xiàng),都是先把 js 文件生成一份字節(jié)碼,然后拼到一個(gè) .c 文件里,大概長(zhǎng)下面的這個(gè)樣子:

        #include <quickjs/quickjs-libc.h>

        const uint32_t qjsc_hello_size = 87;

        // JS 文件編譯生成的字節(jié)碼都在這個(gè)數(shù)組里
        const uint8_t qjsc_hello[87] = {
         0x020x040x0e0x630x6f0x6e0x730x6f,
         0x6c0x650x060x6c0x6f0x670x160x48,
         0x650x6c0x6c0x6f0x200x570x6f0x72,
         0x6c0x640x220x650x780x610x6d0x70,
         0x6c0x650x730x2f0x680x650x6c0x6c,
         0x6f0x2e0x6a0x730x0e0x000x060x00,
         0x9e0x010x000x010x000x030x000x00,
         0x140x010xa00x010x000x000x000x39,
         0xf10x000x000x000x430xf20x000x00,
         0x000x040xf30x000x000x000x240x01,
         0x000xd10x280xe80x030x010x00,
        };

        int main(int argc, char **argv)
        {
          JSRuntime *rt;
          JSContext *ctx;
          rt = JS_NewRuntime();
          ctx = JS_NewContextRaw(rt);
          JS_AddIntrinsicBaseObjects(ctx);
          js_std_add_helpers(ctx, argc, argv);
          js_std_eval_binary(ctx, qjsc_hello, qjsc_hello_size, 0);
          js_std_loop(ctx);
          JS_FreeContext(ctx);
          JS_FreeRuntime(rt);
          return 0;
        }

        因?yàn)檫@是個(gè) .c 文件,想跑起來(lái)還得編譯一次生成二進(jìn)制文件。

        從字節(jié)碼這個(gè)設(shè)計(jì)點(diǎn)來(lái)看,QuickJS 和 Hermes 的定位還是不太一樣的。

        雖然直接生成字節(jié)碼可以大大減少 JS 文本文件的解析時(shí)間,但是 QuickJS 還是更偏嵌入式一些,生成的字節(jié)碼放在一個(gè) C 文件中,還需要進(jìn)行編譯才能運(yùn)行;Hermes 為 React Native 而生,生成的字節(jié)碼一開(kāi)始就考慮到分發(fā)功能(熱更新就是一個(gè)應(yīng)用場(chǎng)景),支持字節(jié)碼的直接加載運(yùn)行,不需要再編譯一次。


        上面主要還是對(duì)性能的考量,下面我們看看開(kāi)發(fā)體驗(yàn)。

        首先是 QuickJS 的調(diào)試功能支持。到目前為止(2021-02-22),QuickJS 還沒(méi)有官方的調(diào)試器,也就是說(shuō) debugger 語(yǔ)句會(huì)被忽略,社區(qū)有人實(shí)現(xiàn)了一套基于 VSCode 的調(diào)試器支持 vscode-quickjs-debug[26],但是會(huì)對(duì) QuickJS 做一些定制,個(gè)人還是蠻期待官方支持某個(gè)調(diào)試器協(xié)議的。

        集成 的角度上看,社區(qū)上已經(jīng)有了 iOS[27]Android[28] 的示例項(xiàng)目,可以拿來(lái)用來(lái)參考接入到自己的工程中。


        綜合來(lái)看,QuickJS 是一款潛力非常大的 JS 引擎,在 JS 語(yǔ)法高度支持的前提下,還把性能和體積都優(yōu)化到了極致。在移動(dòng)端的 Hybrid UI 架構(gòu)和游戲腳本系統(tǒng)都可以考慮接入。

        選型思路

        1.單引擎

        單引擎的意思就是 iOS 端和 Android 端統(tǒng)一采用一個(gè)引擎,這樣做的話(huà)在 JS 層差異可以抹平,不容易出現(xiàn)同一份 JS 代碼在 iOS 上運(yùn)行是好的,Android 上就出錯(cuò)的奇異 BUG。結(jié)合市面上的跨端方案,大概有下面三種選型:

        • 統(tǒng)一采用 JSC:這個(gè)是 React Native 0.60 之前的方案
        • 統(tǒng)一使用 Hermes:這個(gè)是 React Native 0.64 之后的設(shè)計(jì)方案
        • 統(tǒng)一采用 QuickJS:QuickJS 體積很小,可以用來(lái)制作非常輕量的 Hybrid 系統(tǒng)

        上面看出沒(méi)有統(tǒng)一采用 V8,這個(gè)就是我前面說(shuō)的,V8 在 iOS 平臺(tái)沒(méi)有主場(chǎng)優(yōu)勢(shì),關(guān)閉 JIT 后性能和 JSC 差不多,還會(huì)增大包體積,并不是很劃算。

        2.雙引擎

        雙引擎也很好理解,就是 iOS 端和 Android 端各用各的,優(yōu)點(diǎn)是可以發(fā)揮各自的主場(chǎng)優(yōu)勢(shì),缺點(diǎn)是可能會(huì)因?yàn)槠脚_(tái)不一致導(dǎo)致雙端運(yùn)行結(jié)果不統(tǒng)一,現(xiàn)在的方案有這么幾種:

        • iOS 用 JSC,Android 用 V8:Weex,NativeScript 都是這樣的,可以在包體積和性能上有較好的均衡
        • iOS 用 JSC,Android 用 Hermes:React Natvie 現(xiàn)如今的方案
        • iOS 用 JSC,Android 用 QuickJS:滴滴的跨端框架 hummer[29] 就是這樣的設(shè)計(jì)

        從選型上看,iOS 上都選擇了 JSC,Android 各有各的選擇,倒是充分發(fā)揮了兩個(gè)平臺(tái)的特色 : )

        3.調(diào)試

        無(wú)論是單引擎還是雙引擎,集成后的業(yè)務(wù)開(kāi)發(fā)體驗(yàn)也很重要。對(duì)于自帶 debugger 功能的引擎來(lái)說(shuō)一切都不在話(huà)下,但是對(duì)于沒(méi)有實(shí)現(xiàn)調(diào)試協(xié)議的引擎來(lái)說(shuō),缺少 debugger 還是會(huì)影響體驗(yàn)的。

        但不是也沒(méi)有辦法,一般來(lái)說(shuō)我們可以曲線救國(guó),類(lèi)似于 React Native 的 Remote JS Debugging 的思路:

        我們可以加個(gè)開(kāi)關(guān),把 JS 代碼通過(guò) websocket 傳送到 Chrome 的 Web Worker,然后用 Chrome 的 V8 進(jìn)行調(diào)試。這樣做的優(yōu)勢(shì)是可以調(diào)整一些業(yè)務(wù)上的 BUG,劣勢(shì)就是又會(huì)引入一個(gè) JS 引擎,萬(wàn)一遇到一些引擎實(shí)現(xiàn)的 BUG,就很難 debug 了。不過(guò)好在這種情況非常非常少見(jiàn),我們也不能因噎廢食對(duì)吧。

        總結(jié)

        本文從性能體積、調(diào)試便捷性等功能點(diǎn)出發(fā),分析了 JavaScriptCore,V8,HermesQuickJS 這 4 款 JS 引擎,分別分析了它們的缺點(diǎn)和弱點(diǎn)。如果大家有移動(dòng)端 JS 引擎選型的困惑,我認(rèn)為從本文出發(fā),還是可以給不少人以靈感的,希望我的這篇文章能幫助到大家。


        參考資料

        [1]

        三級(jí)目錄: https://www.wikiwand.com/en/WebKit#/JavaScriptCore

        [2]

        RednaxelaFX 大佬: https://www.zhihu.com/people/rednaxelafx

        [3]

        解釋: https://www.zhihu.com/question/21320960/answer/18628710

        [4]

        JS Runtime 頁(yè)面: https://reactnative.dev/docs/javascript-environment#javascript-runtime

        [5]

        J2V8: https://github.com/eclipsesource/J2V8

        [6]

        JIT-less V8: https://v8.dev/blog/jitless

        [7]

        2015: https://v8.dev/blog/custom-startup-snapshots

        [8]

        NativeScript: https://nativescript.org/

        [9]

        博文: https://nativescript.org/blog/improving-app-startup-time-on-android-with-webpack-v8-heap-snapshot/

        [10]

        J2V8-Debugger: https://github.com/AlexTrotsenko/j2v8-debugger

        [11]

        release: https://github.com/facebook/hermes/releases

        [12]

        Hermes 開(kāi)源: https://engineering.fb.com/2019/07/12/android/hermes/

        [13]

        jsc-android: https://www.npmjs.com/package/jsc-android

        [14]

        2019-06-25: https://github.com/react-native-community/jsc-android-buildscripts/commit/abdce96b7ce833d0d33078b4b8a772b6593d7a3f

        [15]

        TTI: https://web.dev/tti/

        [16]

        文檔: https://github.com/facebook/hermes/blob/master/doc/BuildingAndRunning.md

        [17]

        React Native Memory profiling: JSC vs V8 vs Hermes: https://dev.to/anotherjsguy/react-native-memory-profiling-jsc-vs-v8-vs-hermes-1c76

        [18]

        v0.7.0: https://github.com/facebook/hermes/releases/tag/v0.7.0

        [19]

        Debugging JS on Hermes using Google Chrome's DevTools: https://reactnative.dev/docs/hermes#debugging-js-on-hermes-using-google-chromes-devtools

        [20]

        時(shí)間軸: https://bellard.org/

        [21]

        ES2020: https://tc39.es/ecma262/

        [22]

        Test262: https://test262.report/browse/?date=2020-12-16

        [23]

        基準(zhǔn)測(cè)試: https://bellard.org/quickjs/bench.html

        [24]

        Lua vs QuickJS: https://sabotage-linux.neocities.org/blog/9/

        [25]

        生成字節(jié)碼: https://bellard.org/quickjs/quickjs.html#Bytecode

        [26]

        vscode-quickjs-debug: https://github.com/koush/vscode-quickjs-debug

        [27]

        iOS: https://github.com/siuying/QuickJS-iOS

        [28]

        Android: https://github.com/seven332/quickjs-android

        [29]

        hummer: https://hummer.didi.cn/doc#/zh-CN/hummer_design

        [30]

        深入理解JSCore: https://tech.meituan.com/2018/08/23/deep-understanding-of-jscore.html

        [31]

        QuickJS 引擎一年見(jiàn)聞錄: https://zhuanlan.zhihu.com/p/161722203



        瀏覽 342
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            中文字幕第一页不卡 | 伊人精品视频 | 成人性生交无码视频 | 无码不卡永久视频自拍 | 亚洲国产国模大尺度视频 | 北条麻妃黄色视频免费播放 | 少妇高潮叫床声20分钟 | 考逼免费视频 | 国产成人精品视频 | 欧美午夜AⅤ无码精品色情综艺 |