亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > JS > 正文

JavaScript深入V8引擎以及編寫優化代碼的5個技巧

2024-05-06 16:52:41
字體:
來源:轉載
供稿:網友

概述

JavaScript引擎是執行 JavaScript 代碼的程序或解釋器。JavaScript引擎可以實現為標準解釋器,或者以某種形式將JavaScript編譯為字節碼的即時編譯器。

以為實現JavaScript引擎的流行項目的列表:

V8?—?開源,由 Google 開發,用 C ++ 編寫

Rhino?—?由 Mozilla 基金會管理,開源,完全用 Java 開發

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

JavaScriptCore —?開源,以Nitro形式銷售,由蘋果為Safari開發

KJS?—?KDE 的引擎,最初由 Harri Porten 為 KDE 項目中的 Konqueror 網頁瀏覽器開發

Chakra (JScript9)?—?Internet Explorer

Chakra (JavaScript)?—?Microsoft Edge

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

JerryScript?—? 物聯網的輕量級引擎

為什么要創建V8引擎?

由谷歌構建的V8引擎是開源的,使用c++編寫。這個引擎是在谷歌Chrome中使用的,但是,與其他引擎不同的是 V8 也用于流行的 node.js。

image

V8最初被設計用來提高web瀏覽器中JavaScript執行的性能。為了獲得速度,V8 將 JavaScript 代碼轉換成更高效的機器碼,而不是使用解釋器。它通過實現 JIT (Just-In-Time) 編譯器將 JavaScript 代碼編譯為執行時的機器碼,就像許多現代 JavaScript 引擎(如SpiderMonkey或Rhino (Mozilla)) 所做的那樣。這里的主要區別是 V8 不生成字節碼或任何中間代碼。

V8 曾有兩個編譯器

在 V8 的 5.9 版本出來之前,V8 引擎使用了兩個編譯器:

  • full-codegen?—?一個簡單和非常快的編譯器,產生簡單和相對較慢的機器碼。
  • Crankshaft?— 一種更復雜(Just-In-Time)的優化編譯器,生成高度優化的代碼。

V8 引擎也在內部使用多個線程:

  • 主線程執行你所期望的操作:獲取代碼、編譯代碼并執行它
  • 還有一個單獨的線程用于編譯,因此主線程可以在前者優化代碼的同時繼續執行
  • 一個 Profiler 線程,它會告訴運行時我們花了很多時間,讓 Crankshaft 可以優化它們
  • 一些線程處理垃圾收集器

當第一次執行 JavaScript 代碼時,V8 利用 full-codegen 編譯器,直接將解析的 JavaScript 翻譯成機器代碼而不進行任何轉換。這使得它可以非??焖俚亻_始執行機器代碼。請注意,V8 不使用中間字節碼,從而不需要解釋器。

當代碼已經運行一段時間后,分析線程已經收集了足夠的數據來判斷應該優化哪個方法。

接下來,Crankshaft? 從另一個線程開始優化。它將 JavaScript 抽象語法樹轉換為被稱為 Hydrogen 的高級靜態單分配(SSA)表示,并嘗試優化 Hydrogen 圖,大多數優化都是在這個級別完成的。

內聯代碼

第一個優化是提前內聯盡可能多的代碼。內聯是用被調用函數的主體替換調用點(調用函數的代碼行)的過程。這個簡單的步驟允許下面的優化更有意義。

image

隱藏類
JavaScript是一種基于原型的語言:沒有使用克隆過程創建類和對象。JavaScript也是一種動態編程語言,這意味著可以在實例化后輕松地在對象中添加或刪除屬性。

大多數 JavaScript 解釋器使用類似字典的結構(基于哈希函數)來存儲對象屬性值在內存中的位置,這種結構使得在 JavaScript 中檢索屬性的值比在 Java 或 C# 等非動態編程語言中的計算成本更高。

在Java中,所有對象屬性都是在編譯之前由固定對象布局確定的,并且無法在運行時動態添加或刪除(當然,C#具有動態類型,這是另一個主題)。

因此,屬性值(或指向這些屬性的指針)可以作為連續緩沖區存儲在存儲器中,每個緩沖區之間具有固定偏移量, 可以根據屬性類型輕松確定偏移的長度,而在運行時可以更改屬性類型的 JavaScript 中這是不可能的。

由于使用字典查找內存中對象屬性的位置效率非常低,因此 V8 使用了不同的方法:隱藏類。隱藏類與 Java 等語言中使用的固定對象(類)的工作方式類似,只是它們是在運行時創建的?,F在,讓我們看看他們實際的例子:

image

一旦 “new Point(1,2)” 調用發生,V8 將創建一個名為 “C0” 的隱藏類。

image

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

一旦第一個語句“this.x = x”被執行(在“Point”函數內),V8 將創建一個名為 “C1” 的第二個隱藏類,它基于“C0”。 “C1”描述了可以找到屬性 x 的存儲器中的位置(相對于對象指針)。

在這種情況下,“x”存儲在偏移0處,這意味著當將存儲器中的 point 對象視為連續緩沖區時,第一偏移將對應于屬性 “x”。 V8 還將使用 “類轉換” 更新 “C0” ,該類轉換指出如果將屬性 “x” 添加到 point 對象,則隱藏類應從 “C0” 切換到 “C1”。 下面的 point 對象的隱藏類現在是“C1”。

image

每次將新屬性添加到對象時,舊的隱藏類都會更新為指向新隱藏類的轉換路徑。隱藏類轉換非常重要,因為它們允許在以相同方式創建的對象之間共享隱藏類。如果兩個對象共享一個隱藏類并且同一屬性被添加到它們中,則轉換將確保兩個對象都接收相同的新隱藏類以及隨其附帶的所有優化代碼。

當語句 “this.y = y” 被執行時,會重復同樣的過程(在 “Point” 函數內部,“this.x = x”語句之后)。

一個名為“C2”的新隱藏類會被創建,如果將一個屬性 “y” 添加到一個 Point 對象(已經包含屬性“x”),一個類轉換會添加到“C1”,則隱藏類應該更改為“C2”,point 對象的隱藏類更新為“C2”。

image

隱藏類轉換取決于將屬性添加到對象的順序??纯聪旅娴拇a片段:

image

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

內聯緩存

V8利用了另一種優化動態類型語言的技術,稱為內聯緩存。內聯緩存依賴于這樣一種觀察,即對同一方法的重復調用往往發生在同一類型的對象上。這里可以找到對內聯緩存的深入解釋。

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

那么它是如何工作的呢? V8 維護了在最近的方法調用中作為參數傳遞的對象類型的緩存,并使用這些信息預測將來作為參數傳遞的對象類型。如果 V8 能夠很好地預測傳遞給方法的對象的類型,它就可以繞過如何訪問對象屬性的過程,而是使用從以前的查找到對象的隱藏類的存儲信息。

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

內聯緩存也是為什么相同類型的對象共享隱藏類非常重要的原因。 如果你創建兩個相同類型和不同隱藏類的對象(正如我們之前的例子中所做的那樣),V8將無法使用內聯緩存,因為即使這兩個對象屬于同一類型,它們對應的隱藏類為其屬性分配不同的偏移量。

image

這兩個對象基本相同,但是“a”和“b”屬性的創建順序不同。

編譯成機器碼
一旦 Hydrogen 圖被優化,Crankshaft 將其降低到稱為 Lithium 的較低級表示。大部分的 Lithium 實現都是特定于架構的。寄存器分配往往發生在這個級別。

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

有一種叫去優化的安全措施來進行相反的轉換,并在假設引擎無效的情況下返回未優化的代碼。

垃圾收集

對于垃圾收集,V8采用傳統的 mark-and-sweep 算法 來清理舊一代。 標記階段應該停止JavaScript執行。 為了控制GC成本并使執行更穩定,V8使用增量標記:不是遍歷整個堆,嘗試標記每個可能的對象,它只是遍歷堆的一部分,然后恢復正常執行。下一個GC停止將從上一個堆行走停止的位置繼續,這允許在正常執行期間非常短暫的暫停,如前所述,掃描階段由單獨的線程處理。

如何編寫優化的 JavaScript

對象屬性的順序:始終以相同的順序實例化對象屬性,以便可以共享隱藏的類和隨后優化的代碼。

動態屬性: 因為在實例化之后向對象添加屬性將強制執行隱藏的類更改,并降低之前隱藏類所優化的所有方法的執行速度,所以在其構造函數中分配所有對象的屬性。

方法:重復執行相同方法的代碼將比僅執行一次的多個不同方法(由于內聯緩存)的代碼運行得更快。

數組:避免稀疏數組,其中鍵值不是自增的數字,并沒有存儲所有元素的稀疏數組是哈希表。這種數組中的元素訪問開銷較高。另外,盡量避免預分配大數組。最好是按需增長。最后,不要刪除數組中的元素,這會使鍵值變得稀疏。

標記值:V8 使用 32 位表示對象和數值。由于數值是 31 位的,它使用了一位來區分它是一個對象(flag = 1)還是一個稱為 SMI(SMall Integer)整數(flag = 0)。那么,如果一個數值大于 31 位,V8會將該數字裝箱,把它變成一個雙精度數,并創建一個新的對象來存放該數字。盡可能使用 31 位有符號數字,以避免對 JS 對象的高開銷的裝箱操作。

Ignition and TurboFan

隨著2017年早些時候發布V8 5.9,引入了新的執行管道。 這個新的管道在實際的JavaScript應用程序中實現了更大的性能提升和顯著節省內存。

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

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

這意味著 V8 整體上將有更簡單和更易維護的架構。

image

這些改進只是一個開始。 新的Ignition和TurboFan管道為進一步優化鋪平了道路,這些優化將在未來幾年內提升JavaScript性能并縮小V8在Chrome和Node.js中的占用空間。


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美日韩国产精品一区| 亚洲国产欧美精品| 亚洲精品天天看| 国产精品激情av在线播放| 亚洲欧美制服中文字幕| 久久免费观看视频| 日本精品一区二区三区在线播放视频| 伊人久久久久久久久久| 国产视频欧美视频| 亚洲九九九在线观看| 亚洲丝袜在线视频| 欧美视频中文在线看| 日韩成人av在线播放| 国产亚洲人成网站在线观看| 欧美大片在线看| 亚洲精品久久久久久久久久久久| 日韩在线观看免费全集电视剧网站| 国产精品视频在线观看| 欧美国产第一页| 成人免费在线网址| 亚洲精品小视频在线观看| 久久久在线视频| 亚洲一区二区黄| 亚洲自拍偷拍一区| 久久天天躁狠狠躁夜夜躁2014| 在线免费观看羞羞视频一区二区| 国产精品视频在线播放| 成人激情在线播放| 亚洲天堂av网| 性欧美长视频免费观看不卡| 国内精品小视频在线观看| 亚洲福利在线观看| 国产欧美精品va在线观看| 亚洲欧美在线播放| 亚洲午夜性刺激影院| 538国产精品一区二区在线| 亚洲一区二区中文字幕| 国产精品视频xxxx| 日韩影视在线观看| 中文字幕在线看视频国产欧美在线看完整| 91网站在线看| 欧美亚洲激情在线| 国产成人精品在线视频| 97在线视频免费看| 91啪国产在线| 2019亚洲男人天堂| 国产热re99久久6国产精品| 国产精品扒开腿做爽爽爽男男| 国产精品啪视频| 欧美性猛交xxxx免费看漫画| 亚洲无限av看| 神马久久桃色视频| 欧美成人免费一级人片100| 国产精品日韩电影| 日韩欧美黄色动漫| 亚洲精品一区二区三区婷婷月| 欧美激情在线观看视频| 欧美日韩国产精品专区| 亚洲综合自拍一区| 欧美最猛性xxxxx(亚洲精品)| 国产美女久久精品| 久久久999成人| 久久天堂av综合合色| 国产日本欧美一区二区三区| 亚洲精品福利在线| 日韩中文综合网| 久久精品国产亚洲7777| 欧美电影免费播放| 欧美三级免费观看| 国产一区二区精品丝袜| 国产丝袜高跟一区| 国产精品一香蕉国产线看观看| 精品国产一区二区三区在线观看| 欧洲亚洲妇女av| 欧美黑人xxx| 亚洲性线免费观看视频成熟| 伊人伊成久久人综合网站| 久久亚洲精品小早川怜子66| 亚洲视频在线观看视频| 国产欧美一区二区三区久久人妖| 亚洲激情在线观看视频免费| 精品国产91久久久久久| 久久久久久久91| 51久久精品夜色国产麻豆| 九九综合九九综合| 久久久久国产精品免费| 亚洲天堂av电影| 日韩在线观看免费全集电视剧网站| 国产成人精品国内自产拍免费看| 欧美放荡办公室videos4k| 久青草国产97香蕉在线视频| 九九热这里只有精品6| 亚洲国产精彩中文乱码av在线播放| 都市激情亚洲色图| 亚洲欧美另类中文字幕| 丝袜美腿亚洲一区二区| 欧美乱大交xxxxx| 欧美成人精品一区二区三区| 亚洲国产精品专区久久| 国产精品aaaa| 日韩成人在线播放| 国产一区二区香蕉| 国产欧美日韩专区发布| 日韩av中文字幕在线| 色黄久久久久久| 69国产精品成人在线播放| 日韩久久精品电影| 国产精品jizz在线观看麻豆| 亚洲欧美一区二区三区久久| 欧美久久久精品| 成人黄色片在线| 精品久久久久久中文字幕大豆网| 精品亚洲一区二区| 国产成人精品亚洲精品| 日韩欧美中文字幕在线播放| 中文字幕亚洲欧美日韩2019| 欧美成人四级hd版| 欧美激情xxxx| 在线播放国产一区中文字幕剧情欧美| 国产精品一香蕉国产线看观看| 亚洲国产日韩欧美在线动漫| 亚洲欧美国产精品久久久久久久| 日韩经典第一页| 亚洲欧美日韩中文在线| 欧美日韩国产成人在线观看| 国产精品丝袜久久久久久不卡| 欧美黑人一级爽快片淫片高清| 国产一区二区三区视频在线观看| 在线观看日韩视频| 精品久久久久久中文字幕| 国产一区红桃视频| 欧美精品一二区| 亚洲自拍高清视频网站| 亚洲视频专区在线| 久久91精品国产91久久久| 国a精品视频大全| 国产精品永久免费观看| 97视频在线观看视频免费视频| 国产日韩在线看| 欧美国产日韩视频| 日本一区二三区好的精华液| 91免费福利视频| 亚洲欧美中文在线视频| 久久亚洲一区二区三区四区五区高| 欧美黄色片视频| 欧美极品少妇全裸体| 成人a在线视频| 国产成人高清激情视频在线观看| 欧美黑人巨大精品一区二区| 国产精品jizz在线观看麻豆| 久热精品视频在线观看一区| 成人免费视频a| 久久伊人精品一区二区三区| 精品视频在线播放免| 欧美在线欧美在线| 久久躁狠狠躁夜夜爽| 91精品久久久久久久久久久久久| 国产一区玩具在线观看| 欧美精品午夜视频| 韩国v欧美v日本v亚洲| 97国产精品久久| 日韩激情视频在线| 日本a级片电影一区二区| 国产精品成人v|