成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

V8 Ignition:JS 引擎與字節(jié)碼的不解之緣(轉(zhuǎn)載)

lijinke666 / 763人閱讀

摘要:縱覽各個(gè)引擎的實(shí)現(xiàn),我們發(fā)現(xiàn)基于字節(jié)碼的實(shí)現(xiàn)是主流。引入字節(jié)碼之后,的性能得到了顯著的提升。而這次引入字節(jié)碼卻是向著相反的方向后退。這便是引入字節(jié)碼的主要?jiǎng)訖C(jī)。如今也回到了字節(jié)碼的懷抱,不禁令人感嘆引擎與字節(jié)碼真是有著不解之緣

首先貼個(gè)Javascript性能測(cè)試站點(diǎn),測(cè)試并展示了數(shù)個(gè) JavaScript 引擎的性能數(shù)據(jù):arewefastyet

我們看到在這個(gè)比武場(chǎng)上,最近 Chrome 出現(xiàn)了多個(gè)新條目,其中很多條目都是關(guān)于 v8 的 Ignition 新架構(gòu)的組合,他們是 v8 引擎最近推出的 JS 字節(jié)碼解釋器。

縱覽各個(gè) JS 引擎的實(shí)現(xiàn),我們發(fā)現(xiàn)基于字節(jié)碼的實(shí)現(xiàn)是主流。例如蘋果公司的 JavaScriptCore (JSC) 引擎,2008 年時(shí)他們引入了 SquirrelFish(市場(chǎng)名 Nitro),實(shí)現(xiàn)了一個(gè)字節(jié)碼寄存器機(jī)(Register Machine)。再如 Mozilla 公司的 SpiderMonkey,他們使用字節(jié)碼的歷史更久,可以追溯到 1998 年的 Netscape 4(見 https://dxr.mozilla.org/class... ),SpiderMonkey 實(shí)現(xiàn)的是堆棧機(jī)(Stack Machine)。微軟的 Chakra 也使用了字節(jié)碼,他們實(shí)現(xiàn)的是寄存器機(jī)(Register Machine)。而 v8 之前的做法是比較“脫俗”的,他們跳過了字節(jié)碼這一層,直接把 JS 編譯成機(jī)器碼。而在剛剛過去的五一假日前夕,v8 5.9 發(fā)布了,其中的 Ignition 字節(jié)碼解釋器將默認(rèn)啟動(dòng) :https://v8project.blogspot.co... 。v8 自此回到了字節(jié)碼的懷抱。

這讓筆者不禁懷念起 2007 年 Ruby 1.9 的發(fā)布。當(dāng)時(shí) Ruby 1.9 也是第一次引入了字節(jié)碼,名為 YARV,由笹田耕一領(lǐng)導(dǎo)主導(dǎo)開發(fā)完成。當(dāng)時(shí),Ruby 還在使用松本行弘的初級(jí)的解釋器實(shí)現(xiàn),亦即,解釋器每次遍歷代碼的抽象語法樹(AST)來進(jìn)行 Ruby 代碼的解釋執(zhí)行。而 YARV 則把抽象語法樹(AST)先編譯成字節(jié)碼,然后再運(yùn)行。引入字節(jié)碼之后,Ruby 的性能得到了顯著的提升。

而這次 V8 引入字節(jié)碼卻是向著相反的方向后退。因?yàn)橹?v8 選擇了直接將 JS 代碼編譯到機(jī)器代碼執(zhí)行,機(jī)器碼的執(zhí)行性能已經(jīng)非常之高,而這次引入字節(jié)碼則是選擇編譯 JS 代碼到一個(gè)中間態(tài)的字節(jié)碼,執(zhí)行時(shí)是解釋執(zhí)行,性能是低于機(jī)器代碼的。最終的性能測(cè)試勢(shì)必會(huì)降低,而不是提高。那么 V8 為什么要做這樣一個(gè)退步的選擇呢?為 V8 引入字節(jié)碼的動(dòng)機(jī)又是什么呢?筆者總結(jié)下來有三條:

(主要?jiǎng)訖C(jī))減輕機(jī)器碼占用的內(nèi)存空間,即犧牲時(shí)間換空間

提高代碼的啟動(dòng)速度

對(duì) v8 的代碼進(jìn)行重構(gòu),降低 v8 的代碼復(fù)雜度

故事得從 Chrome 的一個(gè) bug 說起: http://crbug.com/593477 。Bug 的報(bào)告人發(fā)現(xiàn),當(dāng)在 Chrome 51 (canary) 瀏覽器下加載、退出、重新加載 facebook 多次,并打開 about:tracing 里的各項(xiàng)監(jiān)控開關(guān),可以發(fā)現(xiàn)第一次加載時(shí) v8.CompileScript 花費(fèi)了 165 ms,再次加載加入 V8.ParseLazy 居然依然花費(fèi)了 376 ms。按說如果 Facebook 網(wǎng)站的 js 腳本沒有變,Chrome 的緩存功能應(yīng)該緩存了對(duì) js 腳本的解析結(jié)果,不該花費(fèi)這么久。這是為什么呢?

這就是之前 v8 將 JS 代碼編譯成機(jī)器碼所帶來的問題。因?yàn)闄C(jī)器碼占空間很大,v8 沒有辦法把 Facebook 的所有 js 代碼編譯成機(jī)器碼緩存下來,因?yàn)檫@樣不僅緩存占用的內(nèi)存、磁盤空間很大,而且退出 Chrome 再打開時(shí)序列化、反序列化緩存所花費(fèi)的時(shí)間也很長,時(shí)間、空間成本都接受不了。

所以 v8 退而求其次,只編譯最外層的 js 代碼,也就是下圖這個(gè)例子里面綠色的部分。那么內(nèi)部的代碼(如下圖中的黃色、紅色的部分)是什么時(shí)候編譯的呢?v8 推遲到第一次被調(diào)用的時(shí)候再編譯。這時(shí)間上的推移還導(dǎo)致另外一個(gè)短板,就是代碼必須被解析多次——綠色的代碼一次、黃色的代碼再解析一次(當(dāng) new Person 被調(diào)用)、紅色的代碼再解析一次(當(dāng) doWork() 被調(diào)用)。因此,如果你的 js 代碼的閉包套了 n 層,那么最終他們至少會(huì)被 v8 解析 n 次。

Facebook 的網(wǎng)站之所以收到這個(gè)設(shè)計(jì)帶來的負(fù)面的性能影響,就是因?yàn)樗麄兊那岸喂こ塘鞒讨凶詈蟀迅鱾€(gè)獨(dú)立的 module 編譯成了一個(gè)多帶帶的文件,其中用到了很多閉包,如:

如此一來 Chrome 的緩存作用就只能作用在最外層的 __d() 代碼上,而內(nèi)部的真正的邏輯根本沒有被緩存。

剛才提到了機(jī)器碼占空間大的一個(gè)壞處,就是不能一次性編譯全部的代碼。機(jī)器碼占空間大還有另外一個(gè)壞處,就是一些只運(yùn)行一次的代碼浪費(fèi)了寶貴的內(nèi)存資源。正如上面 Facebook 中的 __d() 系列函數(shù),他們的作用可能只是注冊(cè)、初始化各個(gè)模塊組件,而一旦初始化完成便不會(huì)再執(zhí)行。但由于機(jī)器碼占空間大,這些只執(zhí)行一次的代碼也會(huì)在內(nèi)存中長期存在、長期占用空間。正如下圖所示,一般情況下大約 30% 的 V8 堆空間都用來存儲(chǔ)未優(yōu)化的機(jī)器碼。

而引入字節(jié)碼之后,占空間的問題就可以得到緩解。通過恰當(dāng)?shù)卦O(shè)計(jì)字節(jié)碼的編碼方式,字節(jié)碼可以做到比機(jī)器碼緊湊很多。V8 引入 Ignition 字節(jié)碼后,代碼的內(nèi)存占用確實(shí)降低了,如下圖所示。

通過對(duì)十大流行手機(jī)端網(wǎng)站的測(cè)試,可以發(fā)現(xiàn)他們的內(nèi)存占用顯著下降。

這便是 v8 引入字節(jié)碼的主要?jiǎng)訖C(jī)。而這樣實(shí)現(xiàn)之后其實(shí)順便又帶來了兩個(gè)好處,筆者認(rèn)為可以視作 v8 引入字節(jié)碼的次要?jiǎng)訖C(jī),亦即:更快的啟動(dòng)速度和更好的 v8 代碼重構(gòu)。

在啟動(dòng)速度方面,如今內(nèi)存占用過大的問題消除了,就可以提前編譯所有代碼了。因?yàn)榍岸斯こ虨榱斯?jié)省網(wǎng)絡(luò)流量,其最終 JS 產(chǎn)品往往不會(huì)分發(fā)無用的代碼,所以可以期望全部提前編譯 JS 代碼不會(huì)因?yàn)榫幾g了過多代碼而浪費(fèi)資源。v8 對(duì)于 Facebook 這樣的網(wǎng)站就可以選擇全部提前編譯 JS 代碼到字節(jié)碼,并把字節(jié)碼緩存下來,如此 Facebook 第二次打開的時(shí)候啟動(dòng)速度就變快了。下圖是舊的 v8 的執(zhí)行時(shí)間的統(tǒng)計(jì)數(shù)據(jù),其中 33% 的解析、編譯 JS 腳本的時(shí)間在新架構(gòu)中就可以被縮短。

v8 自身的重構(gòu)方面,有了字節(jié)碼,v8 可以朝著簡(jiǎn)化的架構(gòu)方向發(fā)展,消除 Cranshaft 這個(gè)舊的編譯器,并讓新的 Turbofan 直接從字節(jié)碼來優(yōu)化代碼,并當(dāng)需要進(jìn)行反優(yōu)化的時(shí)候直接反優(yōu)化到字節(jié)碼,而不需要再考慮 JS 源代碼。最終達(dá)到如下圖所示的架構(gòu)。

其實(shí),Ignition + TurboFan 的組合,就是字節(jié)碼解釋器 + JIT 編譯器的黃金組合。這一黃金組合在很多 JS 引擎中都有所使用,例如微軟的 Chakra,它首先解釋執(zhí)行字節(jié)碼,然后觀察執(zhí)行情況,如果發(fā)現(xiàn)熱點(diǎn)代碼,那么后臺(tái)的 JIT 就把字節(jié)碼編譯成高效代碼,之后便只執(zhí)行高效代碼而不再解釋執(zhí)行字節(jié)碼。蘋果公司的 SquirrelFish Extreme 也引入了 JIT。SpiderMonkey 更是如此,所有 JS 代碼最初都是被解釋器解釋執(zhí)行的,解釋器同時(shí)收集執(zhí)行信息,當(dāng)它發(fā)現(xiàn)代碼變熱了之后,JaegerMonkey、IonMonkey 等 JIT 便登場(chǎng),來編譯生成高效的機(jī)器碼。

回顧歷史,很多 JS 引擎都是采用了字節(jié)碼這一腳本語言實(shí)現(xiàn)技術(shù)的,而 v8 一枝獨(dú)秀,走“純機(jī)器碼”路線,其實(shí)過于激進(jìn)了:雖然執(zhí)行性能上可以登峰造極,但卻帶來了內(nèi)存占用過大的問題。這次引入字節(jié)碼實(shí)則是做了工程上的恰當(dāng)取舍,將損失掉的內(nèi)存找回來,更加符合如今移動(dòng)和嵌入式設(shè)備為主的應(yīng)用場(chǎng)景;以時(shí)間換空間,讓 v8 能更好的服務(wù)于低內(nèi)存的設(shè)備。如今 V8 也回到了字節(jié)碼的懷抱,不禁令人感嘆 JS 引擎與字節(jié)碼真是有著不解之緣!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/83059.html

相關(guān)文章

  • JavaScript深入淺出第4課:V8引擎是如何工作的?

    摘要:摘要性能彪悍的引擎。深入淺出系列深入淺出第課箭頭函數(shù)中的究竟是什么鬼深入淺出第課函數(shù)是一等公民是什么意思呢深入淺出第課什么是垃圾回收算法深入淺出第課是如何工作的最近,生態(tài)系統(tǒng)又多了個(gè)非常硬核的項(xiàng)目。 摘要: 性能彪悍的V8引擎。 《JavaScript深入淺出》系列: JavaScript深入淺出第1課:箭頭函數(shù)中的this究竟是什么鬼? JavaScript深入淺出第2課:函數(shù)是一...

    hsluoyz 評(píng)論0 收藏0
  • JavaScript如何工作:V8引擎深入探究 + 優(yōu)化代碼的5個(gè)技巧(譯文)

    摘要:引擎可以是一個(gè)標(biāo)準(zhǔn)的解釋器,也可以是一個(gè)將編譯成某種形式的字節(jié)碼的即時(shí)編譯器。和其他引擎最主要的差別在于,不會(huì)生成任何字節(jié)碼或是中間代碼。不使用中間字節(jié)碼的表示方式,就沒有必要用解釋器了。 原文地址:https://blog.sessionstack.com... showImg(https://segmentfault.com/img/bVVwZ8?w=395&h=395); 數(shù)周之...

    William_Sang 評(píng)論0 收藏0
  • javascript引擎——V8

    摘要:類將源代碼解釋并構(gòu)建成抽象語法樹,使用類來創(chuàng)建它們,并使用類來分配內(nèi)存。類抽象語法樹的訪問者類,主要用來遍歷抽象語法樹。在該函數(shù)中,先使用類來生成抽象語法樹再使用類來生成本地代碼。 通過上一篇文章,我們知道了JavaScript引擎是執(zhí)行JavaScript代碼的程序或解釋器,了解了JavaScript引擎的基本工作原理。我們經(jīng)常聽說的JavaScript引擎就是V8引擎,這篇文章我們...

    luoyibu 評(píng)論0 收藏0
  • V8 JavaScript 引擎:高性能的 ES2015+

    摘要:最后,客戶端只是依賴于引擎的環(huán)境之一。新的編譯器管道利用來實(shí)現(xiàn),并生成可以轉(zhuǎn)換生成器控制流到簡(jiǎn)單的本地控制流的字節(jié)碼??梢愿菀椎貎?yōu)化所得到的字節(jié)碼,因?yàn)樗恍枰狸P(guān)于生成器控制流的任何具體內(nèi)容,只是如何保存和恢復(fù)函數(shù)的狀態(tài)。 本文轉(zhuǎn)載自:眾成翻譯譯者:smartsrh鏈接:http://www.zcfy.cc/article/2978原文:https://v8project.blo...

    songze 評(píng)論0 收藏0
  • JavaScript是如何工作的:深入V8引擎&編寫優(yōu)化代碼的5個(gè)技巧

    摘要:第二篇文章將深入谷歌的引擎的內(nèi)部。引擎可以實(shí)現(xiàn)為標(biāo)準(zhǔn)解釋器,或者以某種形式將編譯為字節(jié)碼的即時(shí)編譯器。這個(gè)引擎是在谷歌中使用的,但是,與其他引擎不同的是也用于流行的。一種更復(fù)雜的優(yōu)化編譯器,生成高度優(yōu)化的代碼。不是唯一能夠做到的引擎。 本系列的 第一篇文章 主要介紹引擎、運(yùn)行時(shí)和調(diào)用堆棧。第二篇文章將深入谷歌 V8 的JavaScript引擎的內(nèi)部。 想閱讀更多優(yōu)質(zhì)文章請(qǐng)猛戳GitHu...

    Turbo 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<