摘要:的主要組件包含了一個(gè)全新的引擎,稱(chēng)為量子,也稱(chēng)為。這個(gè)新引擎集成了四種不同瀏覽器的最新創(chuàng)新技術(shù),創(chuàng)造出一個(gè)全新的超級(jí)引擎。這可以發(fā)生在多個(gè)圖層上。最終,擁有最高特異性的規(guī)則會(huì)勝出。
原文:Inside a Super Fast CSS Engine: Quantum CSS(Aka Stylo), Lin Clark
注:原文發(fā)布于 2017 年 8 月,本文翻譯于 2018 年 4 月,因此對(duì)文中跟時(shí)間相關(guān)的部分內(nèi)容做了調(diào)整,但不影響核心內(nèi)容。
全新的 CSS 引擎 - Stylo你可能已經(jīng)對(duì)量子項(xiàng)目(Project Quantum)有所耳聞,該項(xiàng)目對(duì) Firefox 瀏覽器的內(nèi)部實(shí)現(xiàn)進(jìn)行了重大重寫(xiě),以求更高性能。
本次重寫(xiě)中,我們使用了并行瀏覽器引擎 Servo 的新技術(shù)。這里要介紹地是我們對(duì)瀏覽器引擎的重大改進(jìn)。
該項(xiàng)目的開(kāi)發(fā)過(guò)程就像是給正在飛行中的飛機(jī)更換引擎。對(duì)于瀏覽器中的各個(gè)組件,我們是逐個(gè)進(jìn)行更改的。這樣,我們就可以在一個(gè)組件準(zhǔn)備就緒后,立刻從 Firefox 中看到最新效果。
Servo 的主要組件包含了一個(gè)全新的 CSS 引擎,稱(chēng)為量子 CSS(Quantum CSS,也稱(chēng)為 Stylo)。
這個(gè)新引擎集成了四種不同瀏覽器的最新創(chuàng)新技術(shù),創(chuàng)造出一個(gè)全新的超級(jí) CSS 引擎。
它充分利用了現(xiàn)代硬件多核心的特性,把所有的工作都變成了并行化操作。這使得它可以提速 2 ~ 4 倍,甚至最大能達(dá)到 18 倍。
在并行化的基礎(chǔ)上,它還結(jié)合了其他瀏覽器現(xiàn)有的最先進(jìn)優(yōu)化技術(shù)。所以,即使拋開(kāi)并行化運(yùn)行技術(shù),它也仍然是個(gè)快速的 CSS 引擎。
這里,我們不禁要問(wèn),這個(gè) CSS 引擎到底做了什么呢?
要回答這個(gè)問(wèn)題,首先要知道 CSS 引擎是什么,它是如何跟瀏覽器其他組件一起工作的。然后,我們?cè)倏纯?Stylo 是如何變得更快的。
CSS 引擎是瀏覽器渲染引擎(Rendering Engine)的重要組成部分。
渲染引擎的工作就是把網(wǎng)頁(yè)的 HTML 和 CSS 文件轉(zhuǎn)化為屏幕上顯示的像素點(diǎn)。
每個(gè)瀏覽器都有一個(gè)渲染引擎。Chrome 的稱(chēng)為 Blink,Edge 的稱(chēng)為 EdgeHTML,Safari 的稱(chēng)為 WebKit,以及 Firefox 的稱(chēng)為 Gecko 。
基本流程要想把文件變?yōu)橄袼攸c(diǎn),所有的渲染引擎基本上都會(huì)做以下相同的工作:
1、把文件解析成瀏覽器能理解的對(duì)象,包括 DOM 。從這個(gè)角度來(lái)說(shuō),DOM 掌握了整個(gè)頁(yè)面結(jié)構(gòu)。它知道每個(gè)元素之間的父子關(guān)系,但是它不知道這些元素具體長(zhǎng)什么樣。
2、弄清楚每個(gè)元素應(yīng)該長(zhǎng)什么樣。對(duì)于每個(gè) DOM 節(jié)點(diǎn),CSS 引擎首先會(huì)弄清楚應(yīng)該對(duì)它應(yīng)用什么 CSS 規(guī)則。然后,會(huì)計(jì)算出每個(gè) CSS 屬性的值。
3、計(jì)算出每個(gè)節(jié)點(diǎn)的尺寸和它在屏幕上的位置。為每個(gè)要在屏幕上顯示的內(nèi)容創(chuàng)建盒模型。這些盒模型不僅僅用來(lái)表示 DOM 節(jié)點(diǎn),它們也用來(lái)表示 DOM 節(jié)點(diǎn)的內(nèi)部?jī)?nèi)容,比如一行一行的文本。
4、繪制不同的盒模型。這可以發(fā)生在多個(gè)圖層上。它就像是以前使用半透明紙的手繪動(dòng)畫(huà),每個(gè)圖層都是獨(dú)立的一張紙。這樣我們就可以只改變當(dāng)前圖層的內(nèi)容,而不會(huì)影響到其他圖層的內(nèi)容。
5、取出已繪制的圖層,應(yīng)用任何僅包含合成器的屬性(比如變換),然后把它們合成為一張圖片。這就好比為這些疊加在一起的圖層拍一張照片,之后這張照片將會(huì)在屏幕上渲染出來(lái)。
從以上過(guò)程可以看出,當(dāng) CSS 引擎開(kāi)始計(jì)算樣式時(shí),它已經(jīng)得到了兩樣?xùn)|西:
DOM 樹(shù)
樣式規(guī)則列表
引擎會(huì)逐個(gè)遍歷所有 DOM 節(jié)點(diǎn),并計(jì)算出它們的樣式。這個(gè)過(guò)程中,它會(huì)給 DOM 節(jié)點(diǎn)的每個(gè) CSS 屬性都進(jìn)行求值,包括樣式表中沒(méi)有聲明的屬性。
這個(gè)過(guò)程就像一個(gè)人從頭到尾填一張表格一樣。CSS 引擎需要給每個(gè) DOM 節(jié)點(diǎn)都填寫(xiě)一張表格。并且,表格的每一處空白都需要填上值。
為了填這張表格,CSS 引擎需要做兩件事:
計(jì)算出每個(gè)節(jié)點(diǎn)應(yīng)該應(yīng)用什么樣式規(guī)則,即選擇器匹配(Selector Matching)
根據(jù)父節(jié)點(diǎn)或默認(rèn)值計(jì)算出缺失的屬性值,即樣式級(jí)聯(lián)(Cascading)
選擇器匹配在這個(gè)步驟中,CSS 引擎會(huì)把所有與 DOM 節(jié)點(diǎn)相匹配的樣式規(guī)則添加到一個(gè)列表中。
因?yàn)榭赡苡卸鄠€(gè)樣式規(guī)則都匹配中,所以可能有多個(gè)相同的 CSS 屬性聲明。
此外,瀏覽器本身也提供了一些默認(rèn)的樣式規(guī)則,即用戶(hù)代理樣式表。
那 CSS 引擎是如何確定應(yīng)該使用哪個(gè)值的呢?
這個(gè)時(shí)候就需要特異性規(guī)則(Specificity Rules)來(lái)幫忙了。
CSS 引擎會(huì)創(chuàng)建一個(gè)電子表格,然后根據(jù)不同的列對(duì)其進(jìn)行排序。
最終,擁有最高特異性的規(guī)則會(huì)勝出。所以,基于這個(gè)表格,CSS 引擎就能夠填充那些它能夠填充的屬性值了。
對(duì)于不能使用這個(gè)方式計(jì)算出的值,它就會(huì)使用樣式級(jí)聯(lián)。
樣式級(jí)聯(lián)樣式級(jí)聯(lián)讓 CSS 的編寫(xiě)和維護(hù)都變得更加簡(jiǎn)單。因?yàn)闃邮郊?jí)聯(lián),你可以在設(shè)置了 的 color 屬性后,直接就知道
、 和 也將會(huì)使用你設(shè)置的顏色值(除非被重寫(xiě)了)。
為了找出級(jí)聯(lián)的樣式屬性,CSS 引擎會(huì)查看表格中的空白部分。
如果屬性默認(rèn)為繼承值,那么 CSS 引擎會(huì)沿著 DOM 樹(shù)往上查找,看看其祖先元素是否已經(jīng)設(shè)置了該值。
如果所有的祖先元素都沒(méi)有設(shè)置該值,或者該屬性并不是繼承,那么就會(huì)使用默認(rèn)值。
至此,一個(gè) DOM 節(jié)點(diǎn)的所有樣式屬性就都已經(jīng)得到計(jì)算值了。
樣式結(jié)構(gòu)共享其實(shí),上面提到的樣式表格與實(shí)際情形并不完全一致。
CSS 擁有的樣式屬性非常多,達(dá)到上百個(gè)。如果 CSS 引擎針對(duì)每個(gè) DOM 節(jié)點(diǎn)的屬性都保存一份樣式值,那么內(nèi)存將會(huì)被迅速耗盡。
相反,CSS 引擎通常會(huì)使用樣式結(jié)構(gòu)共享(Style Struct Sharing)。
它會(huì)把通常在一起使用的樣式值存儲(chǔ)于一個(gè)多帶帶的對(duì)象中,該對(duì)象稱(chēng)為樣式結(jié)構(gòu)。
然后,與其重新存儲(chǔ)相同對(duì)象上的所有樣式值,計(jì)算的樣式對(duì)象實(shí)際只保存了指向那個(gè)對(duì)象的指針。
對(duì)于每個(gè)類(lèi)別的樣式,實(shí)際上存儲(chǔ)的都是一個(gè)指向樣式結(jié)構(gòu)的指針。
這種共享方式既省內(nèi)存又省時(shí)間。這樣的話(huà),具有相似樣式的節(jié)點(diǎn)(比如兄弟節(jié)點(diǎn))就只需要保存指向共享樣式結(jié)構(gòu)對(duì)象的指針即可。而且,由于很多屬性都是繼承來(lái)的,所以祖先節(jié)點(diǎn)可以跟所有的子孫節(jié)點(diǎn)共享相同的樣式結(jié)構(gòu)對(duì)象。
優(yōu)化改進(jìn)上面所說(shuō)的就是優(yōu)化之前的樣式計(jì)算過(guò)程。
這個(gè)過(guò)程中進(jìn)行了很多計(jì)算工作。而且它不只是在第一個(gè)頁(yè)面加載的時(shí)候發(fā)生。它會(huì)在用戶(hù)與頁(yè)面進(jìn)行交互的過(guò)程中反復(fù)的發(fā)生,懸停在元素上或者改變 DOM 結(jié)構(gòu),都會(huì)觸發(fā)樣式重算(Restyle)。
也就是說(shuō),CSS 樣式計(jì)算是一個(gè)舉足輕重的待優(yōu)化點(diǎn)。而且在過(guò)去的 20 年里,各個(gè)瀏覽器一直都在測(cè)試使用不同的策略來(lái)優(yōu)化它。
Stylo 充分吸收了來(lái)自不同引擎的優(yōu)化策略,然后把它們結(jié)合在一起,從而創(chuàng)造出一個(gè)全新的超級(jí)引擎。
下面讓我們來(lái)看看 Stylo 的實(shí)現(xiàn)細(xì)節(jié)。
并行運(yùn)行Servo 是一個(gè)實(shí)驗(yàn)版的瀏覽器,Stylo 就是該項(xiàng)目的一部分。Servo 想把渲染頁(yè)面所需的所有工作都進(jìn)行并行化。
并行化具體指什么呢?
一臺(tái)計(jì)算機(jī)就像一個(gè)大腦。其中有一個(gè)部分是專(zhuān)門(mén)進(jìn)行邏輯思考的,叫做算術(shù)邏輯單元(Arithmetic Logic Unit, ALU)。在 ALU 附近,排列著一些短期記憶存儲(chǔ)單元,稱(chēng)為寄存器(Register)。ALU 和寄存器都是一起放在在 CPU 內(nèi)部的。當(dāng)然也有用于長(zhǎng)期記憶的存儲(chǔ)單元,稱(chēng)為內(nèi)存(RAM)。
使用這種 CPU 的早期計(jì)算機(jī)在同一時(shí)間只能進(jìn)行一種事情。
不過(guò)在過(guò)去的十幾年里,CPU 已經(jīng)進(jìn)化到同時(shí)擁有多個(gè) ALU 和寄存器組,具備了多個(gè)核心。
這就意味著 CPU 可以一次進(jìn)行多種事情,而且是同時(shí)進(jìn)行的。
Stylo 通過(guò)利用計(jì)算機(jī)的這種特性,把不同 DOM 節(jié)點(diǎn)的樣式計(jì)算過(guò)程分配到不同的計(jì)算核心當(dāng)中。
這看起來(lái)是一件很簡(jiǎn)單的事情,只需要把 DOM 樹(shù)的不同分支分開(kāi)來(lái),然后交給不同的核心即可。但實(shí)際上做起來(lái)卻比想象的更加困難,其中一個(gè)原因就是 DOM 樹(shù)通常是不均勻的。這會(huì)導(dǎo)致有些核心做的工作會(huì)比其它的做得多很多。
為了讓工作分配得更加均勻,Stylo 采用了一種稱(chēng)為工作偷竊(Work Stealing)的技術(shù)。當(dāng)處理一個(gè) DOM 節(jié)點(diǎn)時(shí),運(yùn)行的代碼會(huì)把它的子節(jié)點(diǎn)分成一個(gè)或多個(gè)工作單元(Work Units)。這些工作單元會(huì)被添加到一個(gè)隊(duì)列中去。
當(dāng)某個(gè)核心把它的工作隊(duì)列都完成后,它會(huì)查看其它隊(duì)列中的工作單元,然后拿過(guò)來(lái)做。
這樣的話(huà),我們就可以把工作分配得更加均勻,而又不需要花費(fèi)時(shí)間來(lái)遍歷 DOM 樹(shù),也不需要事先就花費(fèi)時(shí)間來(lái)計(jì)算該如何均勻地分配工作。
在大多數(shù)的瀏覽器中,這種并行化工作做起來(lái)非常困難。總所周知,并行化是一塊難啃的硬骨頭,而且 CSS 引擎非常復(fù)雜。同時(shí), CSS 引擎還處于其他兩個(gè)最復(fù)雜部分: DOM 和布局的中間地帶。
因此,這會(huì)非常容易引入 BUG ,而且并行化也會(huì)導(dǎo)致非常難以追查的 BUG,叫做數(shù)據(jù)競(jìng)爭(zhēng)(Data Races)。我在另一篇文章中詳細(xì)介紹了這種類(lèi)型錯(cuò)誤,感興趣的可以參考下。
如果你接受來(lái)自成百上千名工程師的代碼貢獻(xiàn),你是如何做到平行編程而又無(wú)懼 BUG 的呢?這正是 Rust 的用武之地。
在 Rust 中,你可以通過(guò)靜態(tài)檢查的方式來(lái)避免數(shù)據(jù)競(jìng)爭(zhēng)。也就是說(shuō),你可以直接在代碼中就避免這種難以調(diào)試的錯(cuò)誤。編譯器是不會(huì)讓你的代碼存在這樣的問(wèn)題的。
使用 Rust ,CSS 樣式計(jì)算就變成了所謂的完美并行問(wèn)題,因?yàn)槟慊旧喜挥米鍪裁淳蛯?shí)現(xiàn)了并行化。這意味著我們的這個(gè)優(yōu)化可以達(dá)到線性增長(zhǎng)。如果你的機(jī)器有 4 個(gè)核心,那么你就擁有接近 4 被的性能增長(zhǎng)。
規(guī)則樹(shù)對(duì)于每個(gè) DOM 節(jié)點(diǎn),CSS 引擎需要遍歷所有的樣式規(guī)則來(lái)完成選擇器匹配。
但是對(duì)于大多數(shù)節(jié)點(diǎn)來(lái)說(shuō),這種匹配規(guī)則并不是改變的太頻繁。
比如,如果用戶(hù)把光標(biāo)懸停在某個(gè)父元素上,那么匹配中該元素的樣式規(guī)則就可能改變了。我們也需要重新計(jì)算它的后代元素的樣式,以重新處理那些繼承屬性。當(dāng)然,匹配中這些后代元素的規(guī)則也可能是不變的。
如果我們能夠記錄哪些規(guī)則能夠匹配中這些后代元素,那是極好的,這樣我們就不需要對(duì)它們重新進(jìn)行選擇器匹配。這就是我們從 Firefox 上一代 CSS 引擎中借鑒過(guò)來(lái)的規(guī)則樹(shù)(Rule Tree)的原理。
CSS 引擎會(huì)經(jīng)歷選擇器進(jìn)行匹配的整個(gè)過(guò)程,然后按照特異性來(lái)排列它們,由此創(chuàng)建一個(gè)規(guī)則鏈表。
該鏈表會(huì)被添加到規(guī)則樹(shù)中。
CSS引擎會(huì)盡量使得規(guī)則樹(shù)的分支數(shù)量保持在最小值。為此,它會(huì)盡量復(fù)用已存在的規(guī)則分支。
如果鏈表中的選擇器與已存在的分支相同,那么它將順著相同的路徑往下走。不過(guò)它可能最終會(huì)走到一個(gè)下一個(gè)規(guī)則不同的節(jié)點(diǎn)處,只有這個(gè)時(shí)候引擎才會(huì)新增一個(gè)分支。
DOM 節(jié)點(diǎn)會(huì)取得指向這個(gè)規(guī)則最尾端節(jié)點(diǎn)的指針(這個(gè)例子中是 div#warning 規(guī)則)。而且,它的特異性最高的規(guī)則。
在樣式重算時(shí),CSS 引擎會(huì)進(jìn)行一項(xiàng)快速檢查,以判斷對(duì)父元素的變更是否會(huì)影響匹配中子元素的規(guī)則。如果不影響,那么對(duì)于任何后代節(jié)點(diǎn),引擎只需要順著后代節(jié)點(diǎn)保存的規(guī)則指針就可以找到對(duì)應(yīng)規(guī)則分支。在規(guī)則樹(shù)中,只要順著樹(shù)向上遍歷到根節(jié)點(diǎn)就可以獲取所有匹配的樣式規(guī)則。也就是說(shuō),CSS 引擎完全跳過(guò)了選擇器匹配和特異性排列過(guò)程。
這樣我們就減少了樣式重算過(guò)程的計(jì)算量。
雖然如此,但是在樣式初始化時(shí)還是會(huì)耗費(fèi)大量計(jì)算。假如有 10,000 個(gè)節(jié)點(diǎn),仍然需要進(jìn)行 10,000 次選擇器匹配。
不過(guò),不用擔(dān)心,我們還有另一種方式來(lái)優(yōu)化它。
對(duì)于一個(gè)擁有成千上萬(wàn)個(gè)節(jié)點(diǎn)的頁(yè)面,其中有許多節(jié)點(diǎn)都會(huì)匹配中相同的樣式規(guī)則。
舉例來(lái)說(shuō),對(duì)于一個(gè)很長(zhǎng)的維基頁(yè)面,主要內(nèi)容區(qū)的段落應(yīng)該都是應(yīng)用相同的樣式規(guī)則,因此也就有相同的計(jì)算樣式。
如果這里不做優(yōu)化的話(huà),那么 CSS 引擎必須對(duì)每個(gè)段落都進(jìn)行一次選擇器匹配和樣式計(jì)算。
但是如果有一種方式能證明這些不同段落使用的是相同樣式的話(huà),那么引擎就只需要做一次計(jì)算即可,然后其他段落節(jié)點(diǎn)都指向相同的計(jì)算樣式。
這就是我們所說(shuō)的樣式共享緩存(Style Sharing Cache),這種做法的靈感來(lái)自 Safari 和 Chrome 。
當(dāng)處理完一個(gè)節(jié)點(diǎn)之后,引擎會(huì)把計(jì)算樣式放進(jìn)緩存。然后,在開(kāi)始計(jì)算下一個(gè)節(jié)點(diǎn)的樣式之前,引擎會(huì)做一些檢查來(lái)判斷是否可以使用已緩存的樣式。
這些檢查包括:
兩個(gè)節(jié)點(diǎn)是否有相同的 id、class 等?如果是,那么它們可以匹配中相同的樣式規(guī)則。
對(duì)于任何不是基于選擇器的樣式,比如內(nèi)聯(lián)樣式,節(jié)點(diǎn)具有相同的樣式值么?如果是,那么繼承自父節(jié)點(diǎn)的屬性不會(huì)被覆蓋,或者以相同的方式被覆蓋。
節(jié)點(diǎn)的父節(jié)點(diǎn)是否指向相同的計(jì)算樣式對(duì)象?如果是,那么繼承的樣式值則是一樣的。
從樣式共享緩存被提出的一開(kāi)始,這些檢查就已經(jīng)應(yīng)用了。
不過(guò),隨著 CSS 的發(fā)展,有許多其它小場(chǎng)景會(huì)導(dǎo)致樣式共享緩存的檢查方式失效。
比如,如果一個(gè) CSS 規(guī)則使用了 :first-child 選擇器,那么兩個(gè)段落元素時(shí)就可能會(huì)導(dǎo)致樣式不一致,即使上面的那些檢查都認(rèn)為它們是相同的。
在 WebKit 和 Blink 中,樣式共享緩存會(huì)忽略這些場(chǎng)景,并且不使用緩存。
隨著越來(lái)越多的網(wǎng)站使用現(xiàn)代選擇器,樣式共享緩存的優(yōu)化變得越來(lái)越雞肋,因此 Blink 團(tuán)隊(duì)最終還是把它移除了。
但是,事實(shí)證明樣式共享緩存還是有辦法跟上這些進(jìn)化節(jié)奏的。
在 Stylo 中,我們把記錄著所有這些現(xiàn)代選擇器并檢查他們是否能夠適用于 DOM 節(jié)點(diǎn)。然后,我們把檢查結(jié)果以 0 和 1 的方式存儲(chǔ)起來(lái)。如果兩個(gè)元素有相同的 0 和 1 ,那么我們就可以確定它們是匹配的。
如果一個(gè) DOM 節(jié)點(diǎn)可以使用已經(jīng)計(jì)算的樣式緩存,那么引擎就可以直接跳過(guò)大量的計(jì)算過(guò)程。由于頁(yè)面中經(jīng)常有大量的 DOM 節(jié)點(diǎn)擁有相同的樣式規(guī)則,所以樣式共享緩存不僅可以節(jié)省內(nèi)存,同時(shí)也能加快計(jì)算過(guò)程。
結(jié)論Stylo 是第一個(gè)從 Servo 遷移到 Firefox 的大型技術(shù)。
在這個(gè)過(guò)程中,我們已經(jīng)學(xué)到了很多關(guān)于如何把使用 Rust 編寫(xiě)現(xiàn)代高性能代碼集成到 Firefox 核心。
事不宜遲,趕緊下載 Firefox ,體驗(yàn)極速吧!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/113102.html
摘要:現(xiàn)狀年月日,主流的四大瀏覽器達(dá)成了共識(shí)并宣布的最小可行產(chǎn)品已經(jīng)完成。更快的函數(shù)調(diào)用當(dāng)前,在中調(diào)用函數(shù)比想象的要慢。直接操作目前,沒(méi)有任何方式能夠操作。這就導(dǎo)致了部分應(yīng)用可能會(huì)因此而推遲發(fā)布時(shí)間。結(jié)束現(xiàn)如今已經(jīng)相當(dāng)快速。 本文是圖說(shuō) WebAssembly 系列文章的最后一篇。如果您還未閱讀之前的文章,建議您從第一篇入手。 現(xiàn)狀 2017 年 2 月 28 日,主流的四大瀏覽器達(dá)成了共識(shí)...
摘要:編譯器優(yōu)缺點(diǎn)與解釋器相比,編譯器有著相反的優(yōu)缺點(diǎn)。它們?yōu)橐嫘略隽艘粋€(gè)組件,稱(chēng)為監(jiān)視器,或者。優(yōu)化編譯器會(huì)基于監(jiān)視器記錄的代碼運(yùn)行信息來(lái)作出一些判斷。通常來(lái)說(shuō),優(yōu)化編譯器會(huì)使得代碼跑的更快。而這正是優(yōu)化編譯器所做的優(yōu)化之一。 本文是圖說(shuō) WebAssembly 系列文章的第二篇,如果你還沒(méi)閱讀其它的,建議您從第一篇開(kāi)始。 JavaScript 的運(yùn)行,一開(kāi)始是很慢的,但是后面會(huì)變得越來(lái)...
摘要:性能簡(jiǎn)史在年,被創(chuàng)造出來(lái)時(shí)并不是沖著性能去的。而且在之后的十年發(fā)展中,它的性能一直是很低的。的引入成就了性能提升的一個(gè)轉(zhuǎn)折點(diǎn),其執(zhí)行速度比以往快了之多。性能提升也使得在全新的問(wèn)題上使用成為可能。現(xiàn)在,極可能是下一個(gè)性能轉(zhuǎn)折點(diǎn)。 你可能已經(jīng)聽(tīng)說(shuō) WebAssembly 代碼跑起來(lái)非常快。但是你知道這是為什么嗎?在本系列文章中,我們將探究其原因。 何為 WebAssembly WebAss...
摘要:瀏覽器內(nèi)核又叫渲染引擎,主要負(fù)責(zé)的解析,頁(yè)面布局渲染與復(fù)合層合成。頁(yè)面呈現(xiàn)原理規(guī)范定義了的詞法及語(yǔ)法文法。解析器使用和解析生成器從語(yǔ)法文件中自動(dòng)生成解析器?;貞浺幌陆馕銎鞯慕榻B,創(chuàng)建一個(gè)自底向上的解析器,使用自頂向下解析器。 瀏覽器內(nèi)核又叫渲染引擎,主要負(fù)責(zé) HTML、CSS 的解析,頁(yè)面布局、渲染與復(fù)合層合成。瀏覽器內(nèi)核的不同帶來(lái)的主要問(wèn)題是對(duì) CSS 的支持度與屬性表現(xiàn)差異。 we...
摘要:瀏覽器內(nèi)核又叫渲染引擎,主要負(fù)責(zé)的解析,頁(yè)面布局渲染與復(fù)合層合成。頁(yè)面呈現(xiàn)原理規(guī)范定義了的詞法及語(yǔ)法文法。解析器使用和解析生成器從語(yǔ)法文件中自動(dòng)生成解析器?;貞浺幌陆馕銎鞯慕榻B,創(chuàng)建一個(gè)自底向上的解析器,使用自頂向下解析器。 瀏覽器內(nèi)核又叫渲染引擎,主要負(fù)責(zé) HTML、CSS 的解析,頁(yè)面布局、渲染與復(fù)合層合成。瀏覽器內(nèi)核的不同帶來(lái)的主要問(wèn)題是對(duì) CSS 的支持度與屬性表現(xiàn)差異。 we...
閱讀 2935·2023-04-26 01:01
閱讀 3704·2021-11-23 09:51
閱讀 2530·2021-11-22 14:44
閱讀 3633·2021-09-23 11:57
閱讀 2848·2021-09-22 14:58
閱讀 5890·2021-09-10 11:25
閱讀 2117·2019-08-30 13:11
閱讀 1607·2019-08-30 12:59