中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

JavaScript 引擎 V8 Lite Mode 改造 V8

2019-09-22    來源:OSCHINA

容器云強(qiáng)勢上線!快速搭建集群,上萬Linux鏡像隨意使用

去年年底,V8 團(tuán)隊(duì)啟動了一個(gè)名為 V8 Lite 的項(xiàng)目,旨在大幅降低 V8 的內(nèi)存使用率。最開始,團(tuán)隊(duì)準(zhǔn)備把 V8 Lite 作為 V8 的獨(dú)立模式,專門用于低內(nèi)存的移動設(shè)備與嵌入式設(shè)備,因?yàn)檫@些設(shè)備更關(guān)注的是減少內(nèi)存使用而不是執(zhí)行速度。

在這個(gè)項(xiàng)目研發(fā)的過程中,開發(fā)團(tuán)隊(duì)發(fā)現(xiàn)專門為這個(gè) Lite 模式所做的內(nèi)存優(yōu)化其實(shí)也可以遷移到原來的 V8 上,直接兩開花。V8 團(tuán)隊(duì)近日發(fā)表了一個(gè)文章,就詳細(xì)分享了在構(gòu)建 V8 Lite 的過程中將一些關(guān)鍵的優(yōu)化部分帶到現(xiàn)有 V8 上的過程,以及在實(shí)際工作負(fù)載中對 V8 性能表現(xiàn)的影響。下邊簡要介紹一下。

Lite Mode

分析了 V8 如何使用內(nèi)存以及哪些對象類型占 V8 堆大小的比例很大之后,V8 團(tuán)隊(duì)發(fā)現(xiàn),V8 堆的很大一部分專門用于對 JavaScript 執(zhí)行來說不必要的對象,比如用于優(yōu)化 JavaScript 執(zhí)行和處理異常情況。具體來說比如優(yōu)化代碼;用于確定如何優(yōu)化代碼的類型反饋;用于 C++ 和 JavaScript 對象之間綁定的冗余元數(shù)據(jù)等。

所以團(tuán)隊(duì)從這一點(diǎn)入手,想通過大幅減少這些可選對象的內(nèi)存分配來提高內(nèi)存使用。同時(shí)團(tuán)隊(duì)提出了 V8 的 Lite Mode。

通過配置現(xiàn)有的 V8 設(shè)置可以直接應(yīng)用一些 Lite Mode 的優(yōu)化,例如禁用 V8 的 TurboFan 優(yōu)化編譯器,但是現(xiàn)有 V8 想支持其它 Lite Mode 優(yōu)化則需要更多的考慮。

比如在 Ignition 解釋器中執(zhí)行代碼時(shí),V8 收集有關(guān)傳遞給各種操作(例如,+o.foo)的操作數(shù)類型的反饋,以便為以后的優(yōu)化定制這些類型。此信息存儲在反饋向量中,這些向量占 V8 堆內(nèi)存使用量的很大一部分。Lite Mode 不優(yōu)化代碼,所以可以直接不去分配這些反饋向量,但是 V8 的內(nèi)聯(lián)緩存基礎(chǔ)結(jié)構(gòu)的解釋器期望反饋向量可用,因此需要相當(dāng)多的重構(gòu)才能支持 Lite Mode 這種無反饋執(zhí)行。

Lite Mode 在 V8 v7.3 中推出,與 V8 v7.1 相比,通過禁用代碼優(yōu)化、不分配反饋向量并執(zhí)行很少執(zhí)行的字節(jié)碼老化,典型網(wǎng)頁堆大小減少 22%。

同時(shí)在這個(gè)過程中,團(tuán)隊(duì)還發(fā)現(xiàn),可以通過使 V8 更加“Lazy”來實(shí)現(xiàn) Lite Mode 的大部分內(nèi)存節(jié)省,而不會影響性能。

Lazy feedback allocation 

完全禁用反饋向量分配不僅會阻止 V8 的 TurboFan 編譯器優(yōu)化代碼,還會阻止 V8 執(zhí)行常見操作的內(nèi)聯(lián)緩存,例如 Ignition 解釋器中的對象屬性加載。因此,這樣做會導(dǎo)致 V8 的執(zhí)行時(shí)間顯著回退,頁面加載時(shí)間減少 12%,典型交互式網(wǎng)頁方案中 V8 使用的 CPU 時(shí)間增加 120%。

為了在沒有這些回退的情況下將大部分內(nèi)存節(jié)省帶到常規(guī) V8 中,開發(fā)團(tuán)隊(duì)設(shè)計(jì)了在函數(shù)執(zhí)行了一定量的字節(jié)碼(目前為 1KB)之后,延遲分配反饋向量。由于大多數(shù)函數(shù)不經(jīng)常執(zhí)行,因此在大多數(shù)情況下避免使用反饋向量分配,但會在需要的地方快速分配它們以避免性能回退,并仍然允許優(yōu)化代碼。

使用這種方法,會產(chǎn)生另一個(gè)問題。反饋向量會形成樹結(jié)構(gòu),內(nèi)部函數(shù)的反饋向量被保留為外部函數(shù)的反饋向量中的條目。這是必要的,以便新創(chuàng)建的函數(shù)閉包接收與為同一函數(shù)創(chuàng)建的所有其它閉包相同的反饋向量數(shù)組。在延遲分配反饋向量的情況下,無法使用反饋向量來形成這棵樹,因?yàn)闊o法保證外部函數(shù)會在內(nèi)部函數(shù)分配其反饋向量之前就對其進(jìn)行分配。

如下圖,為了解決這個(gè)問題,開發(fā)團(tuán)隊(duì)創(chuàng)建了一個(gè)新的 ClosureFeedbackCellArray 來維護(hù)這個(gè)樹,當(dāng)一個(gè)函數(shù)的 ClosureFeedbackCellArray 變?yōu)?nbsp;Hot 時(shí)將其與一個(gè)完整的 FeedbackVector 交換掉。

實(shí)驗(yàn)顯示桌面延遲反饋沒有出現(xiàn)性能回退,而在移動端,由于垃圾回收減少,性能有所提升,因此 V8 所有版本中都啟用了延遲反饋分配。

Lazy source positions

從 JavaScript 編譯字節(jié)碼時(shí),會生成源位置表,將字節(jié)碼序列綁定到 JavaScript 源代碼中的字符位置。但是,僅在表示異;驁(zhí)行開發(fā)人員任務(wù)(如調(diào)試)時(shí)才需要此信息,因此很少使用。

為了避免這種浪費(fèi),現(xiàn)在編譯字節(jié)碼而不收集源位置(假設(shè)沒有附加調(diào)試器或分析器)。僅在實(shí)際生成堆棧跟蹤時(shí)收集源位置,例如在調(diào)用 Error.stack 或?qū)惓5亩褩8櫞蛴〉娇刂婆_時(shí)。這需要一些成本,因?yàn)樯稍次恢眯枰匦路治龊途幾g函數(shù),但是大多數(shù)網(wǎng)站不會在生產(chǎn)中對堆棧跟蹤進(jìn)行符號化,因此不會看到什么性能影響。

Bytecode flushing

從 JavaScript 源編譯的字節(jié)碼,包括相關(guān)的元數(shù)據(jù)占用了大量的 V8 堆空間,通常約為 15%。但是有許多函數(shù)只在初始化期間執(zhí)行,或者在編譯后很少使用。所以,V8 針對最近沒有執(zhí)行的情況,添加了在垃圾回收期間支持從函數(shù)中刷新已編譯字節(jié)碼的功能。

具體機(jī)制是,跟蹤函數(shù)字節(jié)碼的 age,每次主要(mark-compact)垃圾回收 age 都遞增,并在執(zhí)行函數(shù)時(shí)將其重置為零。任何超過老化閾值的字節(jié)碼都可以被下一次垃圾回收回收,如果它被回收然后再次執(zhí)行,則會重新編譯。

這么設(shè)計(jì)的難點(diǎn)在于確保字節(jié)碼僅在不再需要的情況下才可以被刷新。例如,如果函數(shù) A 調(diào)用另一個(gè)長時(shí)間運(yùn)行的函數(shù) B,函數(shù) A 可能會在它仍然在堆棧上時(shí)老化。這時(shí)候我們并不想刷新函數(shù) A 的字節(jié)碼,即使它達(dá)到了老化閾值,因?yàn)檫需要在長時(shí)間運(yùn)行的函數(shù) B 返回時(shí)返回它。

解決這個(gè)問題的方法是,當(dāng)字節(jié)碼達(dá)到其老化閾值時(shí),將字節(jié)碼視為弱保持狀態(tài)(weakly held),但是在堆棧或其它地方對字節(jié)碼的任何引用將強(qiáng)烈保持(strongly held),并且只在沒有強(qiáng)鏈接的情況下才可以刷新代碼。

除了刷新字節(jié)碼,同時(shí)還刷新與這些刷新函數(shù)相關(guān)的反饋向量。但是,無法在與字節(jié)碼相同的 GC 周期內(nèi)刷新反饋向量,因?yàn)樗鼈儾粫煌粚ο蟊A簟W止?jié)碼由本地上下文獨(dú)立的 SharedFunctionInfo 保留,而反饋向量由本地上下文相關(guān)的 JSFunction 保留。因此,會在隨后的 GC 循環(huán)中刷新反饋向量。

Additional optimizations

此外開發(fā)團(tuán)隊(duì)還通過減小 FunctionTemplateInfo 對象的大小和對 TurboFan 優(yōu)化代碼進(jìn)行去優(yōu)化等方面的優(yōu)化減少了內(nèi)存使用。

Results

目前已經(jīng)在 V8 的最新七個(gè)版本中發(fā)布了上述優(yōu)化,通常它們會先應(yīng)用在 Lite Mode 中,然后再進(jìn)入 V8 的默認(rèn)配置。

經(jīng)過測試,在一系列典型網(wǎng)站上將 V8 堆大小平均減少了 18%,相當(dāng)于低端 AndroidGo 移動設(shè)備平均減少 1.5 MB。

通過禁用功能優(yōu)化,Lite Mode 可以以一定的開銷進(jìn)一步為 JavaScript 執(zhí)行吞吐量提供內(nèi)存節(jié)省。平均而言,Lite Mode 可節(jié)省 22% 的內(nèi)存,有些頁面可節(jié)省高達(dá) 32% 的內(nèi)存。這相當(dāng)于 AndroidGo 設(shè)備上 V8 堆大小減少了 1.8 MB。

具體分析每一種優(yōu)化技術(shù)帶來的影響,結(jié)果如下:

完整優(yōu)化介紹查看原博客:

https://v8.dev/blog/v8-lite

標(biāo)簽: [db:TAGG]

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點(diǎn)!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請與原作者聯(lián)系。

上一篇:uiw 3.5.1 發(fā)布,更新圖標(biāo)組件

下一篇:高性能網(wǎng)絡(luò)通信框架 HP-Socket v5.6.1