91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

移動端JS的引擎有哪些

發布時間:2021-10-18 15:11:59 來源:億速云 閱讀:214 作者:iii 欄目:web開發

這篇文章主要介紹“移動端JS的引擎有哪些”,在日常操作中,相信很多人在移動端JS的引擎有哪些問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”移動端JS的引擎有哪些”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

JS 引擎選型要點

JavaScript 作為世界上最熱門的腳本語言,有著非常多的引擎實現:有 Apple 御用的  JavaScriptCore,有性能最強勁的 V8,還有最近熱度很高的 QuickJS......如何從這些 JS  引擎里選出最適合的?我個人認為要有幾個考量:

  • 性能:這個沒話說,肯定是越快越好

  • 體積:JS 引擎會增加一定的包體積

  • 內存占用:內存占用越少越好

  • JavaScript 語法支持程度:支持的新語法越多越好

  • 調試的便捷性:是否直接支持 debug?還是需要自己編譯實現調試工具鏈

  • 應用市場平臺規范:主要是 iOS 平臺,平臺禁止應用集成帶 JIT 功能的虛擬機

比較麻煩的是,上面的幾個點都不是互相獨立的:

比如說開啟 JIT 的 V8 引擎,性能肯定是最好的,但它引擎體積就很大,內存占用也很高;在包體積上很占優勢的 QuickJS,由于沒有 JIT  加持,和有 JIT 的引擎比起來平均會有 5-10 倍的性能差距。

下面我會綜合剛剛提到的幾個點,并選擇了 JavaScriptCore,V8,Hermes 和 QuickJS 這 4 個  JSVM,說說它們的優點和特點,再談談他們的不足。

JS 引擎功能大比拼

1.JavaScriptCore

移動端JS的引擎有哪些

              mobile_JSVM_JSC

JavaScriptCore 是 WebKit 默認的內嵌 JS 引擎,wikipedia 上都沒有獨立的詞條,只在 WebKit  詞條的三級目錄[1]里介紹了一下,個人感覺還是有些不像話,畢竟也是老牌 JS 引擎了。

由于 WebKit 是 Apple 率先開源的,所以 WebKit 引擎運用在 Apple 自家的 Safari 瀏覽器和 WebView 上,尤其是  iOS 系統上,因為 Apple 的限制,所有的網頁只能用 WebKit 加載,所以 WebKit 在 iOS 上達到了事實壟斷,作為 WebKit  模塊一部分的 JSC,順著政策春風,也「基本」壟斷了 iOS 平臺的 JS 引擎份額。

壟斷歸壟斷,其實 JSC 的性能還是可以的。

很多人不知道 JSC 的 JIT 功能其實比 V8 還要早,放在十幾年前是最好的 JS 引擎,只不過后來被 V8 追了上來。而且 JSC 有個重大利好,在  iOS7 之后,JSC 作為一個系統級的 Framework 開放給開發者使用,也就是說,如果你的 APP 使用 JSC,只需要在項目里 import  一下,包體積是 0 開銷的!這點在今天討論的 JS 引擎中,JSC 是最能打的。

雖然開啟 JIT 的 JSC 性能很好,但是只限于蘋果御用的 Safari 瀏覽器和 WKWebView,只有這兩個地方 JIT  功能才是默認開啟的,如果在項目里直接引入 JSC,JIT 功能是關閉的。為什么這么做呢?RednaxelaFX 大佬[2] 給出過非常專業的解釋[3]:

JIT  編譯需要底層系統支持動態代碼生成,對操作系統來說這意味著要支持動態分配帶有“可寫可執行”權限的內存頁。當一個應用程序擁有請求分配可寫可執行內存頁的權限時,它會比較容易受到攻擊從而允許任意代碼動態生成并執行,這樣就讓惡意代碼更容易有機可乘。

Apple 出于安全上的考慮,禁止了第三方 APP 使用 JSC 時開啟 JIT,這些特點在 React Native 的 JS Runtime  頁面[4]也有過相關的解釋。不過在實際應用中,不做重 CPU 的運算只當膠水語言使用,JSC 還是綽綽有余了。

上面的討論都是針對 iOS 系統的,在 Android 系統上,JSC 的表現就不盡人意了。

JSC 并沒有對 Android 機型做很好的適配,雖然可以開啟 JIT,但是性能表現并不好,這也是 Facebook 決心制作 Hermes  的一個原因,具體的性能對比分析可見本文的 Hermes 小節。

最后再說說 JSC 的調試支持情況。如果是 iOS 平臺,我們可以直接用 Safari 的 debbuger 功能調試,如果是 Android  平臺,目前我還沒有找到一個很好的真機調試方法。

綜合來看,JavaScriptCore 在 iOS 平臺上有非常明顯的主場優勢,各個指標都是很優秀的,但在 Android  上因為缺乏優化,表現并不是很好。

2.V8

移動端JS的引擎有哪些

mobile_JSVM_V8

V8,我想我不用過多解釋了,JavaScript 能有如今的地位,V8 功不可沒。性能沒得說,開啟 JIT 后就是業內最強(不止是 JS),有很多介紹  V8 的文章,我這里就不多描述了,我們這里說說 V8 在移動端的表現。

同樣作為 Google 家的產品,每一臺 Android 手機上都安裝了基于 Chromium 的 WebView,V8 也一并捆綁了。但是 V8 和  Chromium 捆綁的太緊密了,不像 iOS 上的 JavaScriptCore 封裝為系統庫可以被所有 App 調用。這就導致你想在 Android 上用  V8 還得自己封裝,社區比較出名的項目是 J2V8[5],提供了 V8 的 Java bindings 案例。

V8 性能沒得說,Android 上可以開啟 JIT,但這些優勢都是有代價的:開啟 JIT 后內存占用高,并且 V8 的包體積也不小(大概 7 MB  左右),如果作為只是畫 UI 的 Hybrid 系統,還是有些奢侈了。

我們再說說 V8 在 iOS 上的集成。

V8 在 2019 年推出了 JIT-less V8[6],也就是關閉 JIT 只使用 Ignition interpreter 解釋執行 JS  文件,那么我們在 iOS 上集成 V8 就成了可能,因為 Apple 還是支持接入只有解釋器功能的虛擬機引擎的。但是個人認為關閉了 JIT 的 V8 接入  iOS 價值不大,因為只開啟解釋器的話,這時候的 V8 和 JSC 的性能其實是差不多的,引入反而會增加一定的體積開銷。

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

堆快照是什么原理呢?一般來說 JSVM 啟動后,第一步往往是解析 JS 文件,這個還是比較耗時的,V8 支持預先生成 Heap  snapshots,然后直接加載到堆內存中,快速的獲得 JS 的初始化上下文。跨平臺框架 NativeScript[8] 就利用了這樣的技術,可以讓 JS  的加載速度提升 3 倍,技術細節可以看他們的博文[9]。

移動端JS的引擎有哪些

V8_heap_snapshots

V8 真機調試也需要引入第三方庫,Android 端社區上有人對 J2V8 做了 Chrome 調試協議的擴展,即 J2V8-Debugger[10]  項目,iOS 我沒有找到相關的項目,可能需要自己實現一套擴展。

綜合來看 V8 的確是 JSVM 中的性能王者,Android 端使用時可以完全發揮它的威力,但是 iOS 平臺因為主場劣勢,并不是很推薦。

3.Hermes

移動端JS的引擎有哪些

mobile_JSVM_hermes

Hermes 是 FaceBook 2019 年中旬開源的一款 JS 引擎,從 release[11] 記錄可以看出,這個是專為 React Native  打造的 JS 引擎,可以說從設計之初就是為 Hybrid UI 系統打造。

Hermes 一開始推出就是要替代原來 RN Android 端的 JS 引擎,即 JavaScriptCore(因為 JSC 在 Android  端表現太拉垮了)。我們可以理一下時間線,FaceBook 自從 2019-07-12 宣布 Hermes 開源[12]后,jsc-android[13]  的維護信息就永遠的停在了 2019-06-25[14],這個信號暗示得非常的明顯:JavaScriptCore Android  我們不再維護啦,大家都去用我們做的 Hermes 啊。

最近 Hermes 已經計劃伴隨 React Native 0.64 版本登錄 iOS 平臺了,但是 RN 版本更新 blog  還沒有出,大家可以看看我之前對 Apple 開發者協議的解讀:Apple Agreement 3.3.2 規范解讀,在這里我就不多說了。

Hermes 的特點主要是兩個,一個是不支持 JIT,一個是支持直接生成/加載字節碼,我們在下面分開講一下。

Hermes 不支持 JIT 的主要原因有兩個:加入 JIT 后,JS 引擎啟動的預熱時間會變長,一定程度上會加長首屏  TTI[15](頁面首次加載可交互時間),現在的前端頁面都講究一個秒開,TTI 還是個挺重要的測量指標。另一個問題上 JIT  會增加包體積和內存占用,Chrome 內存占用高 V8 還是要承擔一定責任的。

因為不支持 JIT,Hermes 在一些 CPU 密集計算的領域就不占優勢了,所以在 Hybrid 系統里,最優的解決方案就是充分發揮  JavaScript 膠水語言的作用,CPU 密集的計算(例如矩陣變換,參數加密等)放在 Native 里做,算好了再傳遞給 JS 表現在 UI  上,這樣可以兼顧性能和開發效率。

Hermes 最引人矚目的就是支持生成字節碼了,我在之前的博文《? 跨端框架的核心技術到底是什么?》也提到過,Hermes 加入 AOT  后,Babel、Minify、Parse 和 Compile 這些流程全部都在開發者電腦上完成,直接下發字節碼讓 Hermes 運行就行,我們直接用個 demo  演示一下。

移動端JS的引擎有哪些

Hermes

先寫個 test.js 的文件,里面隨便寫點啥都行;然后編譯一下 Hermes 的源碼,編譯過程直接按文檔[16]來就行,我這里就略過了。

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

hermes test.js

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

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

然后就會生成一份 test.hbc 字節碼文件:

移動端JS的引擎有哪些

hermes_bytecode

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

hermes test.hbc

客觀評價一下 Hermes 的字節碼,首先省去了在 JS 引擎里解析編譯的流程,JS 代碼的加載速度將會大大加快,體現在 UI 上就是 TTI  時間會明顯縮短;另一個優勢 Hermes 的字節碼在設計時就考慮了移動端的性能限制,支持增量加載而不是全量加載,對內存受限的中低端 Android  機更友好;不過字節碼的體積會比原來的 JS 文件會大一些,但是考慮到 Hermes 引擎本身體積就不大,綜合考慮下來這些體積增量還是可以接受的。

關于詳細的 Hermes 性能測試情況,網上有兩篇文章寫的比較好:一篇是 React Native Memory profiling: JSC vs V8  vs Hermes[17],可以看到在 Android 設備上 Hermes 的表現還是很優異的,而 JSC 的表現非常拉垮:

移動端JS的引擎有哪些

JSCvsV8vsHermes

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

移動端JS的引擎有哪些

JSVM_CPU_Performance

說完性能我們再說說 Hermes 的 JS 語法支持情況。

Hermes 主要支持的是 ES6 語法,剛開源時不支持 Proxy,不過 v0.7.0[18] 已經支持了。他們的團隊也比較有想法,不支持 with  eval() 等這種屬于設計糟粕的 API,這種設計的權衡我個人還是比較認同的。

最后我們談談 Hermes 的調試功能。

目前 Hermes 已經支持了 Chrome 的調試協議,我們可以直接用 Chrome 的 debugging 工具直接調試 Hermes  引擎,具體的操作可見文檔:Debugging JS on Hermes using Google Chrome's DevTools[19]

綜合來看,Hermes 是一款專為移動端 Hybrid UI System 打造的 JS 引擎,如果要自建一套 Hybrid 系統,Hermes  是一個非常好的選擇。

4.QuickJS

移動端JS的引擎有哪些

mobile_JSVM_quickjs

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

軟件界一直有個說法,一個高級程序員創造的價值可以超過 20 個平庸的程序員,但 Fabrice Bellard  不是高級程序員,他是天才,在我看來他的創造力可以超過 20 個高級程序員,我們可以順著時間軸[20]理一下他創造過些什么:

  • 1997年,發布了最快速的計算圓周率的算法,此算法是 Bailey-Borwein-Plouffe  公式的變體,前者的時間復雜度是O(n^3),他給優化成了O(n^2),使得計算速度提高了43%,這是他在數學上的成就

  • 2000 年,發布了 FFmpeg,這是他在音視頻領域的一個成就

  • 2000,2001,2018 三年三度獲得國際混淆 C 代碼大賽

  • 2002 年,發布了TinyGL,這是他在圖形學領域的成就

  • 2005 年,發布了 QEMU,這是他在虛擬化領域的成就

  • 2011 年,他用 JavaScript 寫了一個 PC 虛擬機 Jslinux,一個跑在瀏覽器上的 Linux 操作系統

  • 2019 年,發布了 QuickJS,一個支持 ES2020 規范的 JS 虛擬機

當人和人之間的差距差了幾個數量級后,羨慕嫉妒之類的情緒就會轉變為崇拜了,Bellard 就是一個這樣的人。

收復一下心情,我們來看一下 QuickJS 這個項目。QuickJS 繼承了 Fabrice Bellard 作品的一貫特色——小巧而又強大。

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

移動端JS的引擎有哪些

test262

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

移動端JS的引擎有哪些

JSVM_Benchmark

結合上面的表格和個人的一些測試,可以簡單的得出一些結論:

  • 開啟 JIT 的 V8 綜合評分差不多是 QuickJS 的 35 倍,但是在同等主打輕量的 JS 引擎中,QuickJS 的性能還是很耀眼的

  • 在內存占用上,QuickJS 遠低于 V8,畢竟 JIT 是是吃內存的大戶,而且 QuickJS 的設計對嵌入式系統很友好(Bellard 成就獎杯 ?  再 +1)

  • QuickJS 和 Hermes 的跑分情況是差不多的,我私下做了一些性能測試,這兩個引擎的表現也很相近

因為 QuickJS 的設計,我不經好奇他和 Lua 的性能對比如何。

Lua 是一門非常小巧精悍的語言,在游戲領域和 C/C++ 開發中一直充當膠水語言的作用。

我個人寫了一些測試用例,發現 QuickJS 和 Lua 的執行效率也是差不多的,后來在網上找到一篇博文 Lua vs  QuickJS[24],這個老哥也做了一些測試,結論也是它倆的性能差不多,在部分場景 Lua 會比 QuickJS 快一些。

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

我一開始以為 QuickJS 和 Hermes 一樣,可以直接生成字節碼,然后交給 QuickJS 解釋執行。后來自己編譯了一下才發現,QuickJS  的作用機制和 Hermes 還不太一樣:qjsc 生成字節碼的 -e 和 -c 選項,都是先把 js 文件生成一份字節碼,然后拼到一個 .c  文件里,大概長下面的這個樣子:

#include <quickjs/quickjs-libc.h>  const uint32_t qjsc_hello_size = 87;  // JS 文件編譯生成的字節碼都在這個數組里 const uint8_t qjsc_hello[87] = {  0x02, 0x04, 0x0e, 0x63, 0x6f, 0x6e, 0x73, 0x6f,  0x6c, 0x65, 0x06, 0x6c, 0x6f, 0x67, 0x16, 0x48,  0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72,  0x6c, 0x64, 0x22, 0x65, 0x78, 0x61, 0x6d, 0x70,  0x6c, 0x65, 0x73, 0x2f, 0x68, 0x65, 0x6c, 0x6c,  0x6f, 0x2e, 0x6a, 0x73, 0x0e, 0x00, 0x06, 0x00,  0x9e, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00,  0x14, 0x01, 0xa0, 0x01, 0x00, 0x00, 0x00, 0x39,  0xf1, 0x00, 0x00, 0x00, 0x43, 0xf2, 0x00, 0x00,  0x00, 0x04, 0xf3, 0x00, 0x00, 0x00, 0x24, 0x01,  0x00, 0xd1, 0x28, 0xe8, 0x03, 0x01, 0x00, };  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; }

因為這是個 .c 文件,想跑起來還得再編譯一次生成二進制文件。

從字節碼這個設計點來看,QuickJS 和 Hermes 的定位還是不太一樣的。

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

上面主要還是對性能的考量,下面我們看看開發體驗。

首先是 QuickJS 的調試功能支持。到目前為止(2021-02-22),QuickJS 還沒有官方的調試器,也就是說 debugger  語句會被忽略,社區有人實現了一套基于 VSCode 的調試器支持vscode-quickjs-debug[26],但是會對 QuickJS  做一些定制,個人還是蠻期待官方支持某個調試器協議的。

從 集成 的角度上看,社區上已經有了 iOS[27] 和 Android[28] 的示例項目,可以拿來用來參考接入到自己的工程中。

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

選型思路

1.單引擎

單引擎的意思就是 iOS 端和 Android 端統一采用一個引擎,這樣做的話在 JS 層差異可以抹平,不容易出現同一份 JS 代碼在 iOS  上運行是好的,Android 上就出錯的奇異 BUG。結合市面上的跨端方案,大概有下面三種選型:

  • 統一采用 JSC:這個是 React Native 0.60 之前的方案

  • 統一使用 Hermes:這個是 React Native 0.64 之后的設計方案

  • 統一采用 QuickJS:QuickJS 體積很小,可以用來制作非常輕量的 Hybrid 系統

上面看出沒有統一采用 V8,這個就是我前面說的,V8 在 iOS 平臺沒有主場優勢,關閉 JIT 后性能和 JSC  差不多,還會增大包體積,并不是很劃算。

2.雙引擎

雙引擎也很好理解,就是 iOS 端和 Android  端各用各的,優點是可以發揮各自的主場優勢,缺點是可能會因為平臺不一致導致雙端運行結果不統一,現在的方案有這么幾種:

  • iOS 用 JSC,Android 用 V8:Weex,NativeScript 都是這樣的,可以在包體積和性能上有較好的均衡

  • iOS 用 JSC,Android 用 Hermes:React Natvie 現如今的方案

  • iOS 用 JSC,Android 用 QuickJS:滴滴的跨端框架 hummer[29] 就是這樣的設計

從選型上看,iOS 上都選擇了 JSC,Android 各有各的選擇,倒是充分發揮了兩個平臺的特色 : )

3.調試

無論是單引擎還是雙引擎,集成后的業務開發體驗也很重要。對于自帶 debugger 功能的引擎來說一切都不在話下,但是對于沒有實現調試協議的引擎來說,缺少  debugger 還是會影響體驗的。

但不是也沒有辦法,一般來說我們可以曲線救國,類似于 React Native 的 Remote JS Debugging 的思路:

我們可以加個開關,把 JS 代碼通過 websocket 傳送到 Chrome 的 Web Worker,然后用 Chrome 的 V8  進行調試。這樣做的優勢是可以調整一些業務上的 BUG,劣勢就是又會引入一個 JS 引擎,萬一遇到一些引擎實現的 BUG,就很難 debug  了。不過好在這種情況非常非常少見,我們也不能因噎廢食對吧。

到此,關于“移動端JS的引擎有哪些”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

js
AI

九龙坡区| 伊川县| 稻城县| 新竹市| 桦甸市| 开原市| 珲春市| 定远县| 新昌县| 交城县| 扎囊县| 林州市| 彰化县| 西平县| 通州区| 新乡县| 皋兰县| 株洲县| 台北市| 吉林省| 泌阳县| 海口市| 文山县| 镇康县| 积石山| 利津县| 长海县| 丽水市| 新化县| 中方县| 思茅市| 醴陵市| 桐柏县| 亚东县| 荆州市| 沧源| 瑞丽市| 湖州市| 青阳县| 贵州省| 孙吴县|