更輕量的 V8
2018 年底,我們啟動了一個名為 V8 Lite 的專案,目的是顯著減少 V8 的記憶體使用量。起初,這項專案被構想為 V8 的一個獨立 輕量模式,專門針對低記憶體的行動裝置或注重記憶體使用而非執行速度的嵌入式案例。然而,在此期間,我們意識到許多為這個 輕量模式 開發的記憶體優化技術可以應用到常規的 V8,從而讓所有 V8 的使用者受益。
2018 年底,我們啟動了一個名為 V8 Lite 的專案,目的是顯著減少 V8 的記憶體使用量。起初,這項專案被構想為 V8 的一個獨立 輕量模式,專門針對低記憶體的行動裝置或注重記憶體使用而非執行速度的嵌入式案例。然而,在此期間,我們意識到許多為這個 輕量模式 開發的記憶體優化技術可以應用到常規的 V8,從而讓所有 V8 的使用者受益。
之前,我們討論了 JavaScript 引擎如何通過使用形狀和內線快取來優化物件和數組訪問,並探索了引擎如何加速原型屬性訪問。本文敘述 V8 如何為各種 JavaScript 值選擇最佳的內存表示方式,以及這如何影響形狀機制——這有助於解釋React 核心中最近的 V8 性能崖。
注意: 如果你比較喜歡觀看演講而非閱讀文章,請欣賞以下影片!如果不是,跳過影片繼續閱讀。
要運行一個JavaScript程序,需要對源代碼文本進行處理,以便V8能夠理解它。V8首先將源代碼解析為抽象語法樹(AST),這是一組表示程序結構的物件。該AST由Ignition編譯為位元碼。這些解析和編譯階段的性能非常重要:V8在編譯完成之前無法運行代碼。在這一系列的博客文章中,我們將重點關注解析以及V8為提供極速解析器所做的工作。
V8 v7.4 現已支援在執行期間不分配可執行記憶體的 JavaScript 執行功能。
在其預設配置中,V8 大量依賴於在執行期間分配和修改可執行記憶體的能力。例如,TurboFan 優化編譯器會針對熱 JavaScript 函式即時生成原生代碼,而多數 JavaScript 正則表達式則由 irregexp 引擎編譯成原生代碼。在執行期間創建可執行記憶體是 V8 快速的部分原因。
V8 的內建函數 (builtins) 在每個 V8 實例中消耗記憶體。內建函數的數量、平均大小以及每個 Chrome 瀏覽器分頁的 V8 實例數量顯著增加。本文介紹了我們如何在過去一年內將每個網站的V8堆積大小中位數減少了19%。
本文介紹了一種稱為_並行標記_的垃圾回收技術。此優化使 JavaScript 應用程式能在垃圾回收器掃描堆進行標記存活物件時繼續執行。基準測試顯示,並行標記可將主執行緒上的標記時間減少60%–70%。並行標記是Orinoco專案的最後一塊拼圖——該專案旨在逐步將舊的垃圾回收器替換為新的大部分並行和平行垃圾回收器。並行標記在 Chrome 64 和 Node.js v10中為預設啟用。