日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

解讀 JavaScript 之 V8 引擎及優(yōu)化代碼的 5 個(gè)技巧

瀏覽:26日期:2023-11-11 15:03:40

幾個(gè)星期前,我們開始了一系列旨在深入研究 JavaScript 及其實(shí)際工作方式的系列文章:我們認(rèn)為通過了解 JavaScript 的構(gòu)建塊以及它們?nèi)绾我黄饏f(xié)作的,你將能夠編寫更好的代碼和應(yīng)用程序。

本系列的第一篇文章重點(diǎn)介紹了引擎,運(yùn)行時(shí)和調(diào)用堆棧的概述。第二篇文章將深入到 Google V8 JavaScript 引擎的內(nèi)部。我們還將提供一些關(guān)于如何編寫更好的 JavaScript 代碼的快速技巧 - 我們的 SessionStack 開發(fā)團(tuán)隊(duì)在構(gòu)建產(chǎn)品時(shí)所遵循的最佳實(shí)踐。

概覽

JavaScript 引擎是執(zhí)行 JavaScript 代碼的程序或解釋器。 JavaScript 引擎可以作為標(biāo)準(zhǔn)解釋器或即時(shí)編譯器,它以某種形式將 JavaScript 編譯為字節(jié)碼。

下面是一個(gè)實(shí)現(xiàn)了 JavaScript 引擎的流行項(xiàng)目列表:

V8 — 開源,由 Google 開發(fā),用 C ++ 編寫

Rhin o — 由 Mozilla 基金會(huì)管理,開源,完全用 Java 開發(fā)

SpiderMonkey — 是第一個(gè)支持 Netscape Navigator 的 JavaScript 引擎,目前正供 Firefox 使用

JavaScriptCore — 開源,由蘋果公司為 Safari 開發(fā)

KJS — KDE 的引擎,最初由 Harri Porten 為 KDE 項(xiàng)目中的 Konqueror 網(wǎng)頁瀏覽器開發(fā)

Chakra (JScript9) — Internet Explorer

Chakra (JavaScript) — Microsoft Edge

Nashorn , 作為 OpenJDK 的一部分,由 Oracle Java 語言和工具組編寫

JerryScript — 物聯(lián)網(wǎng)的輕量級(jí)引擎

為什么創(chuàng)建 V8 引擎?

由 Google 構(gòu)建的 V8 引擎是開源的,用 C ++ 編寫。 此引擎被用在 Google Chrome 中。 與其他引擎不同的是,V8 也被用于流行的 Node.js 中。

解讀 JavaScript 之 V8 引擎及優(yōu)化代碼的 5 個(gè)技巧

V8 最初是被設(shè)計(jì)用來提高網(wǎng)頁瀏覽器內(nèi)部 JavaScript 執(zhí)行的性能。為了獲得更快的速度,V8 將 JavaScript 代碼翻譯成更高效的機(jī)器代碼,而不是使用解釋器來翻譯代碼。它通過使用 JIT(Just-In-Time)編譯器(如 SpiderMonkey 或 Rhino(Mozilla)等許多現(xiàn)代 JavaScript 引擎)來將 JavaScript 代碼編譯為機(jī)器代碼。 這里的主要區(qū)別在于 V8 不生成字節(jié)碼或任何中間代碼。

V8 曾有兩個(gè)編譯器

在 V8 的 5.9 版本出來之前(今年早些時(shí)候發(fā)布),引擎使用了兩個(gè)編譯器:

full-codegen - 一個(gè)簡單而且速度非常快的編譯器,可以生成簡單且相對較慢的機(jī)器代碼。

Crankshaft - 一種更復(fù)雜(Just-In-Time)的優(yōu)化編譯器,生成高度優(yōu)化的代碼。

V8 引擎也在內(nèi)部使用多個(gè)線程:

主線程完成您期望的任務(wù):獲取代碼,編譯并執(zhí)行它

還有一個(gè)單獨(dú)的線程用于編譯,以便主線程可以繼續(xù)執(zhí)行,而前者正在優(yōu)化代碼

一個(gè) Profiler 線程,它會(huì)告訴運(yùn)行時(shí)我們花了很多時(shí)間,讓 Crankshaft 可以優(yōu)化它們

一些線程處理垃圾收集器

當(dāng)?shù)谝淮螆?zhí)行 JavaScript 代碼時(shí),V8 利用 full-codegen 編譯器,直接將解析的 JavaScript 翻譯成機(jī)器代碼而不進(jìn)行任何轉(zhuǎn)換。這使得它可以非常快速地開始執(zhí)行機(jī)器代碼。請注意,V8 不使用中間字節(jié)碼,從而不需要解釋器。

當(dāng)你的代碼運(yùn)行了一段時(shí)間,分析器線程已經(jīng)收集了足夠的數(shù)據(jù)來判斷哪個(gè)方法應(yīng)該被優(yōu)化。

接下來,Crankshaft 從另一個(gè)線程開始優(yōu)化。它將 JavaScript 抽象語法樹轉(zhuǎn)換為被稱為 Hydrogen 的高級(jí)靜態(tài)單分配(SSA)表示,并嘗試優(yōu)化 Hydrogen 圖。大多數(shù)優(yōu)化都是在這個(gè)級(jí)別完成的。

內(nèi)聯(lián)代碼

第一個(gè)優(yōu)化是提前盡可能多地內(nèi)聯(lián)代碼。內(nèi)聯(lián)是將被調(diào)用函數(shù)的主體替換為調(diào)用站點(diǎn)(調(diào)用函數(shù)的代碼行)的過程。這個(gè)簡單的步驟使得下面的優(yōu)化更有意義。

解讀 JavaScript 之 V8 引擎及優(yōu)化代碼的 5 個(gè)技巧

JavaScript 是一種基于原型的語言:沒有類和對象而是使用克隆創(chuàng)建的。 JavaScript 也是一種動(dòng)態(tài)編程語言,這意味著屬性可以在實(shí)例化后方便地添加或從對象中移除。

大多數(shù) JavaScript 解釋器使用類似字典的結(jié)構(gòu)(基于散列函數(shù))來存儲(chǔ)對象屬性值在內(nèi)存中的位置。這種結(jié)構(gòu)使得在 JavaScript 中檢索一個(gè)屬性的值比在 Java 或 C# 這樣的非動(dòng)態(tài)編程語言中的計(jì)算量要大得多。在 Java 中,所有的對象屬性都是在編譯之前由一個(gè)固定的對象決定的,并且不能在運(yùn)行時(shí)動(dòng)態(tài)添加或刪除(當(dāng)然,C#的動(dòng)態(tài)類型是另一個(gè)主題)。因此,屬性的值(或指向這些屬性的指針)可以作為連續(xù)的緩沖區(qū)存儲(chǔ)在內(nèi)存中,每個(gè)值之間有一個(gè)固定的偏移量。偏移量的長度可以很容易地根據(jù)屬性類型來確定,而在運(yùn)行時(shí)屬性類型可以改變的 JavaScript 中這是不可能的。

由于使用字典查找內(nèi)存中對象屬性的位置效率非常低,因此 V8 使用了不同的方法:隱藏類。隱藏類與 Java 等語言中使用的固定對象(類)的工作方式類似,除了隱藏類是在運(yùn)行時(shí)創(chuàng)建的這點(diǎn)區(qū)別。現(xiàn)在,讓我們看看他們實(shí)際的例子:

function Point(x, y) { this.x = x; this.y = y;}var p1 = new Point(1, 2);

一旦 “new Point(1,2)” 調(diào)用發(fā)生,V8 將創(chuàng)建一個(gè)名為 “C0” 的隱藏類。

解讀 JavaScript 之 V8 引擎及優(yōu)化代碼的 5 個(gè)技巧

尚未為 Point 定義屬性,因此“C0”為空。

一旦第一個(gè)語句 “this.x = x” 被執(zhí)行(在 “Point” 函數(shù)內(nèi)部),V8 將創(chuàng)建第二個(gè)隱藏的類,名為“C1”,它基于“C0”。 “C1”描述了可以找到屬性x的在內(nèi)存中的位置(相對于對象指針)。在這種情況下,“x”被存儲(chǔ)在0處,這意味著當(dāng)在內(nèi)存中將點(diǎn)對象看作一段連續(xù)存儲(chǔ)空間時(shí),第一個(gè)地址將對應(yīng)于屬性“x”。 V8 也會(huì)用“class transition”來更新“C0”,如果一個(gè)屬性“x”被添加到一個(gè)點(diǎn)對象時(shí),隱藏類應(yīng)該從“C0”切換到“C1”。下面的點(diǎn)對象的隱藏類現(xiàn)在是“C1”。

解讀 JavaScript 之 V8 引擎及優(yōu)化代碼的 5 個(gè)技巧

每當(dāng)一個(gè)新的屬性被添加到一個(gè)對象時(shí),舊的隱藏類將被更新為到新的隱藏類的轉(zhuǎn)換路徑。隱藏的類轉(zhuǎn)換非常重要,因?yàn)樗鼈冊试S隱藏的類在以相同方式創(chuàng)建的對象之間共享。如果兩個(gè)對象共享一個(gè)隱藏類,并將相同的屬性添加到這兩個(gè)對象,則轉(zhuǎn)換將確保兩個(gè)對象接收相同的新隱藏類和所有優(yōu)化代碼。

當(dāng)語句 “this.y = y” 被執(zhí)行時(shí),會(huì)重復(fù)同樣的過程(在 “Point” 函數(shù)內(nèi)部,“this.x = x”語句之后)。

一個(gè)名為“C2”的新隱藏類會(huì)被創(chuàng)建,如果將一個(gè)屬性 “y” 添加到一個(gè) Point 對象(已經(jīng)包含屬性“x”),一個(gè)類轉(zhuǎn)換會(huì)添加到“C1”,則隱藏類應(yīng)該更改為“C2”,點(diǎn)對象的隱藏類更新為“C2”。

解讀 JavaScript 之 V8 引擎及優(yōu)化代碼的 5 個(gè)技巧

隱藏類轉(zhuǎn)換取決于將屬性添加到對象的順序。看看下面的代碼片段:

function Point(x, y) { this.x = x; this.y = y;}var p1 = new Point(1, 2);p1.a = 5;p1.b = 6;var p2 = new Point(3, 4);p2.b = 7;p2.a = 8;

現(xiàn)在,假設(shè)對于p1和p2,將使用相同的隱藏類和轉(zhuǎn)換。那么,對于“p1”,首先添加屬性“a”,然后添加屬性“b”。然而,“p2”首先分配“b”,然后是“a”。因此,由于不同的轉(zhuǎn)換路徑,“p1”和“p2”以不同的隱藏類別結(jié)束。在這種情況下,以相同的順序初始化動(dòng)態(tài)屬性好得多,以便隱藏的類可以被重用。

內(nèi)聯(lián)緩存

V8 利用另一種被稱為內(nèi)聯(lián)緩存的技術(shù)來優(yōu)化動(dòng)態(tài)類型語言。內(nèi)聯(lián)緩存依賴于發(fā)生在相同類型的對象上的相同方法的重復(fù)調(diào)用的觀察上。內(nèi)嵌緩存的更多解釋可以在 這里找到 。

接下來將討論內(nèi)聯(lián)緩存的一般概念(如果您沒有時(shí)間通過上面的深入了解)。

它是怎樣工作的? V8 維護(hù)一個(gè)在最近的方法調(diào)用中作為參數(shù)傳遞的對象類型的緩存,并使用這些信息來預(yù)測將來作為參數(shù)傳遞的對象的類型。如果V8能夠很好地假定傳遞給方法的對象類型,那么它可以繞過如何訪問對象的屬性的過程,而是將之前查找到的信息用于對象的隱藏類。

那么隱藏類和內(nèi)聯(lián)緩存的概念如何相關(guān)呢?無論何時(shí)在特定對象上調(diào)用方法時(shí),V8 引擎都必須執(zhí)行對該對象的隱藏類的查找,以確定訪問特定屬性的偏移量。在同一個(gè)隱藏類的兩次成功的調(diào)用之后,V8 省略了隱藏類的查找,并簡單地將該屬性的偏移量添加到對象指針本身。對于該方法的所有下一次調(diào)用,V8 引擎都假定隱藏的類沒有更改,并使用從以前的查找存儲(chǔ)的偏移量直接跳轉(zhuǎn)到特定屬性的內(nèi)存地址。這大大提高了執(zhí)行速度。

內(nèi)聯(lián)緩存也是為什么相同類型的對象可以共享隱藏類非常重要的原因。如果你創(chuàng)建了兩個(gè)相同類型的對象和不同的隱藏類(就像我們之前的例子中那樣),V8 將不能使用內(nèi)聯(lián)緩存,因?yàn)榧词箖蓚€(gè)對象是相同的類型,它們相應(yīng)的隱藏類為其屬性分配不同的偏移量。

解讀 JavaScript 之 V8 引擎及優(yōu)化代碼的 5 個(gè)技巧

這兩個(gè)對象基本相同,但“a”和“b”屬性的創(chuàng)建順序不同。

編譯成機(jī)器碼

一旦 Hydrogen 圖被優(yōu)化,Crankshaft 將其降低到稱為 Lithium 的較低級(jí)表示。大部分的 Lithium 實(shí)現(xiàn)都是特定于架構(gòu)的。寄存器分配往往發(fā)生在這個(gè)級(jí)別。

最后,Lithium 被編譯成機(jī)器碼。然后就是 OSR :on-stack replacement(堆棧替換)。在我們開始編譯和優(yōu)化一個(gè)明確的長期運(yùn)行的方法之前,我們可能會(huì)運(yùn)行堆棧替換。 V8 不只是緩慢執(zhí)行堆棧替換,并再次開始優(yōu)化。相反,它會(huì)轉(zhuǎn)換我們擁有的所有上下文(堆棧,寄存器),以便在執(zhí)行過程中切換到優(yōu)化版本上。這是一個(gè)非常復(fù)雜的任務(wù),考慮到除了其他優(yōu)化之外,V8 最初還將代碼內(nèi)聯(lián)。 V8 不是唯一能夠做到的引擎。

有一種叫做去優(yōu)化的保護(hù)措施來做出相反的變換,并且在假設(shè)引擎優(yōu)化無效的情況下,還原回非優(yōu)化的代碼。

垃圾收集

對于垃圾收集,V8 采用了傳統(tǒng)的分代式掃描方式來清理老一代。標(biāo)記階段應(yīng)該停止 JavaScript 的執(zhí)行。為了控制 GC 成本并使執(zhí)行更加穩(wěn)定,V8 使用了漸進(jìn)式標(biāo)記:而不是走遍整個(gè)堆內(nèi)容,試圖標(biāo)記每一個(gè)可能的對象。它只走一部分堆內(nèi)容,然后恢復(fù)正常執(zhí)行。下一個(gè) GC 將從先前堆走過的地方繼續(xù)執(zhí)行。這允許在正常執(zhí)行期間非常短的暫停。如前所述,掃描階段由不同的線程處理。

Ignition 和 TurboFan

隨著 2017 年早些時(shí)候 V8 5.9 的發(fā)布,一個(gè)新的執(zhí)行管道被引入。這個(gè)新的管道在實(shí)際的 JavaScript 應(yīng)用程序中實(shí)現(xiàn)了更大的性能改進(jìn)和顯著的內(nèi)存節(jié)省。

新的執(zhí)行流程是建立在 Ignition ( V8 的解釋器)和 TurboFan ( V8 的最新優(yōu)化編譯器)之上的。

你可以查看 V8 團(tuán)隊(duì)關(guān)于 這個(gè) 話題的博客文章。

自從 V8 5.9 版本問世以來,由于 V8 團(tuán)隊(duì)一直努力跟上新的 JavaScript 語言特性以及這些特性所需要的優(yōu)化,V8 團(tuán)隊(duì)已經(jīng)不再使用 full-codegen 和 Crankshaft(自 2010 年以來為 V8 技術(shù)所服務(wù))。

這意味著 V8 整體上將有更簡單和更易維護(hù)的架構(gòu)。

解讀 JavaScript 之 V8 引擎及優(yōu)化代碼的 5 個(gè)技巧

在 Web 和 Node.js 性能上的提升

來自:https://www.oschina.net/translate/how-does-javascript-actually-work-part-2

標(biāo)簽: JavaScript
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
青青青国产精品| 日韩视频不卡| 亚欧成人精品| 蜜臀av一区二区三区| 免费日韩av片| 免费在线观看不卡| 亚洲v天堂v手机在线| 日韩在线网址| 国产精品伊人| 福利一区视频| 成人日韩在线观看| 国产中文在线播放| 九色porny丨国产首页在线| 91精品一区国产高清在线gif| 欧美粗暴jizz性欧美20| 九一精品国产| 免费观看久久久4p| 欧美伊人影院| 日产午夜精品一线二线三线| 久久国产中文字幕| 视频精品一区二区| 日韩av黄色在线| 欧美国产极品| 91亚洲国产成人久久精品| 久久久水蜜桃av免费网站| 日韩视频久久| 亚洲精品国产精品粉嫩| 国产精品久久久免费| 伊人久久视频| 久热精品在线| 国产福利亚洲| 91精品久久久久久久久久不卡| 亚洲在线网站| 久久精品xxxxx| 色乱码一区二区三区网站| 亚洲婷婷在线| 亚洲69av| 首页国产精品| 亚洲免费激情| 国产伦精品一区二区三区视频 | 国产精品一区二区精品视频观看| 精品日本视频| 影音先锋久久| 美女尤物国产一区| 国产一区清纯| 国产精品亚洲产品| 91成人精品| 国产精品22p| 欧美精品一二| 国产精品一区二区av日韩在线| 国产在线成人| 老司机精品视频网| 欧美专区在线| 日产精品一区| 国产欧美日韩影院| 久久精品不卡| 国产精品成人**免费视频| 欧美特黄视频| 国产va免费精品观看精品视频| 亚洲欧美网站| 精品欧美日韩精品| 日韩精品一级中文字幕精品视频免费观看 | 日韩中文在线电影| 亚洲精品少妇| 美女少妇全过程你懂的久久| 国产精品红桃| 99综合视频| 欧美xxxx中国| 亚洲精品美女91| 99久久婷婷这里只有精品| 国产精品久久久久av蜜臀| 久久亚洲一区| 欧美一级精品| 精品三级久久久| 日本强好片久久久久久aaa| 国产综合精品| av中文资源在线资源免费观看| 亚洲毛片网站| 亚洲黄色影院| 日韩欧美视频专区| 老司机免费视频一区二区| 亚洲精品一区二区在线播放∴| 欧美日韩水蜜桃| 欧美好骚综合网| 国产精品主播| 婷婷成人av| 久久国产精品99国产| 99久久视频| 日韩免费视频| 粉嫩av一区二区三区四区五区 | 国产精品1区| 日本成人一区二区| 在线看片日韩| 欧美中文日韩| 在线综合视频| 夜夜精品视频| 亚洲黄色在线| 欧美在线影院| 午夜国产一区二区| 99久久夜色精品国产亚洲1000部| 精品国产乱码久久久久久1区2匹| 综合国产精品| 久久成人一区| 国产一区91| 午夜久久免费观看| 婷婷国产精品| 亚洲高清激情| 91久久国产| 久久精品国产68国产精品亚洲| 日韩国产一区二区| 蜜桃av.网站在线观看| 吉吉日韩欧美| 亚洲精品国产嫩草在线观看 | 正在播放日韩精品| 91综合网人人| 成人午夜在线| 91中文字幕精品永久在线| 国产一区二区久久久久| 国产精品99一区二区三区| 国内一区二区三区| 国产一区福利| 福利一区在线| 日韩久久一区二区三区| 日韩免费在线| 一区二区三区视频免费观看| 999国产精品| 国产一级一区二区| 羞羞答答国产精品www一本| 一本色道精品久久一区二区三区| 久久香蕉精品| 欧美日韩a区| 国产精品久久免费视频| 精品久久久久中文字幕小说| 91亚洲成人| 香蕉精品久久| 先锋亚洲精品| 日韩精品第一| 精品一区二区三区亚洲| 日韩欧美午夜| 国产精品视区| 日韩高清一区在线| 精品黄色一级片| 国产传媒在线观看| 欧美亚洲国产一区| 热久久久久久久| 91精品国产自产精品男人的天堂 | 欧美日韩在线播放视频| 爽爽淫人综合网网站| 日本不卡在线视频| 九九九精品视频| 久久久久蜜桃| 午夜久久av | 日本免费一区二区三区四区| 亚洲精品午夜av福利久久蜜桃| 亚洲久久在线| 精品视频久久| 欧美午夜不卡影院在线观看完整版免费| 亚洲一区二区毛片| 国产欧美大片| 久久久久.com| 亚洲精品三级| 日本久久综合| 视频一区欧美日韩| 国产精品久久久免费| 久久九九国产| 日本午夜精品一区二区三区电影| 久久99免费视频| 九九综合九九| 国产日韩欧美在线播放不卡| 人人精品亚洲| 7777精品| 亚洲午夜一级| 国产伦精品一区二区三区千人斩| 99久久婷婷| 国产精品亚洲综合色区韩国| 99精品在线免费在线观看| 深夜福利一区| 肉色欧美久久久久久久免费看 | 麻豆国产91在线播放| 亚洲婷婷免费| 国产精品极品在线观看| 黄色亚洲在线| 国产第一亚洲| 免费不卡在线观看| 欧美激情国产在线| 日韩欧美中文字幕一区二区三区| 超碰99在线| 日韩中文一区二区| 日本精品影院| 欧美日韩xxxx| 亚洲欧美日韩精品一区二区| 91中文字幕精品永久在线| 日本久久一区| 日韩视频免费| 精品一区二区三区中文字幕| 亚洲精品三级| 欧美日韩免费观看一区=区三区| 黄色网一区二区| 日韩av午夜在线观看| 9国产精品视频|