国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

圖說 Firefox 全新 CSS 引擎

lsxiao / 810人閱讀

摘要:的主要組件包含了一個全新的引擎,稱為量子,也稱為。這個新引擎集成了四種不同瀏覽器的最新創新技術,創造出一個全新的超級引擎。這可以發生在多個圖層上。最終,擁有最高特異性的規則會勝出。

原文:Inside a Super Fast CSS Engine: Quantum CSS(Aka Stylo), Lin Clark

注:原文發布于 2017 年 8 月,本文翻譯于 2018 年 4 月,因此對文中跟時間相關的部分內容做了調整,但不影響核心內容。

全新的 CSS 引擎 - Stylo

你可能已經對量子項目(Project Quantum)有所耳聞,該項目對 Firefox 瀏覽器的內部實現進行了重大重寫,以求更高性能。
本次重寫中,我們使用了并行瀏覽器引擎 Servo 的新技術。這里要介紹地是我們對瀏覽器引擎的重大改進。

該項目的開發過程就像是給正在飛行中的飛機更換引擎。對于瀏覽器中的各個組件,我們是逐個進行更改的。這樣,我們就可以在一個組件準備就緒后,立刻從 Firefox 中看到最新效果。

Servo 的主要組件包含了一個全新的 CSS 引擎,稱為量子 CSS(Quantum CSS,也稱為 Stylo)。

這個新引擎集成了四種不同瀏覽器的最新創新技術,創造出一個全新的超級 CSS 引擎。

它充分利用了現代硬件多核心的特性,把所有的工作都變成了并行化操作。這使得它可以提速 2 ~ 4 倍,甚至最大能達到 18 倍。

在并行化的基礎上,它還結合了其他瀏覽器現有的最先進優化技術。所以,即使拋開并行化運行技術,它也仍然是個快速的 CSS 引擎。

這里,我們不禁要問,這個 CSS 引擎到底做了什么呢?
要回答這個問題,首先要知道 CSS 引擎是什么,它是如何跟瀏覽器其他組件一起工作的。然后,我們再看看 Stylo 是如何變得更快的。

CSS 引擎原理

CSS 引擎是瀏覽器渲染引擎(Rendering Engine)的重要組成部分。
渲染引擎的工作就是把網頁的 HTML 和 CSS 文件轉化為屏幕上顯示的像素點。

每個瀏覽器都有一個渲染引擎。Chrome 的稱為 Blink,Edge 的稱為 EdgeHTML,Safari 的稱為 WebKit,以及 Firefox 的稱為 Gecko 。

基本流程

要想把文件變為像素點,所有的渲染引擎基本上都會做以下相同的工作:

1、把文件解析成瀏覽器能理解的對象,包括 DOM 。從這個角度來說,DOM 掌握了整個頁面結構。它知道每個元素之間的父子關系,但是它不知道這些元素具體長什么樣。

2、弄清楚每個元素應該長什么樣。對于每個 DOM 節點,CSS 引擎首先會弄清楚應該對它應用什么 CSS 規則。然后,會計算出每個 CSS 屬性的值。

3、計算出每個節點的尺寸和它在屏幕上的位置。為每個要在屏幕上顯示的內容創建盒模型。這些盒模型不僅僅用來表示 DOM 節點,它們也用來表示 DOM 節點的內部內容,比如一行一行的文本。

4、繪制不同的盒模型。這可以發生在多個圖層上。它就像是以前使用半透明紙的手繪動畫,每個圖層都是獨立的一張紙。這樣我們就可以只改變當前圖層的內容,而不會影響到其他圖層的內容。

5、取出已繪制的圖層,應用任何僅包含合成器的屬性(比如變換),然后把它們合成為一張圖片。這就好比為這些疊加在一起的圖層拍一張照片,之后這張照片將會在屏幕上渲染出來。

從以上過程可以看出,當 CSS 引擎開始計算樣式時,它已經得到了兩樣東西:

DOM 樹

樣式規則列表

引擎會逐個遍歷所有 DOM 節點,并計算出它們的樣式。這個過程中,它會給 DOM 節點的每個 CSS 屬性都進行求值,包括樣式表中沒有聲明的屬性。

這個過程就像一個人從頭到尾填一張表格一樣。CSS 引擎需要給每個 DOM 節點都填寫一張表格。并且,表格的每一處空白都需要填上值。

為了填這張表格,CSS 引擎需要做兩件事:

計算出每個節點應該應用什么樣式規則,即選擇器匹配(Selector Matching)

根據父節點或默認值計算出缺失的屬性值,即樣式級聯(Cascading)

選擇器匹配

在這個步驟中,CSS 引擎會把所有與 DOM 節點相匹配的樣式規則添加到一個列表中。
因為可能有多個樣式規則都匹配中,所以可能有多個相同的 CSS 屬性聲明。

此外,瀏覽器本身也提供了一些默認的樣式規則,即用戶代理樣式表。
那 CSS 引擎是如何確定應該使用哪個值的呢?

這個時候就需要特異性規則(Specificity Rules)來幫忙了。
CSS 引擎會創建一個電子表格,然后根據不同的列對其進行排序。

最終,擁有最高特異性的規則會勝出。所以,基于這個表格,CSS 引擎就能夠填充那些它能夠填充的屬性值了。

對于不能使用這個方式計算出的值,它就會使用樣式級聯。

樣式級聯

樣式級聯讓 CSS 的編寫和維護都變得更加簡單。因為樣式級聯,你可以在設置了 color 屬性后,直接就知道

、

  • 也將會使用你設置的顏色值(除非被重寫了)。

    為了找出級聯的樣式屬性,CSS 引擎會查看表格中的空白部分。
    如果屬性默認為繼承值,那么 CSS 引擎會沿著 DOM 樹往上查找,看看其祖先元素是否已經設置了該值。
    如果所有的祖先元素都沒有設置該值,或者該屬性并不是繼承,那么就會使用默認值。

    至此,一個 DOM 節點的所有樣式屬性就都已經得到計算值了。

    樣式結構共享

    其實,上面提到的樣式表格與實際情形并不完全一致。
    CSS 擁有的樣式屬性非常多,達到上百個。如果 CSS 引擎針對每個 DOM 節點的屬性都保存一份樣式值,那么內存將會被迅速耗盡。

    相反,CSS 引擎通常會使用樣式結構共享(Style Struct Sharing)。
    它會把通常在一起使用的樣式值存儲于一個多帶帶的對象中,該對象稱為樣式結構。
    然后,與其重新存儲相同對象上的所有樣式值,計算的樣式對象實際只保存了指向那個對象的指針。
    對于每個類別的樣式,實際上存儲的都是一個指向樣式結構的指針。

    這種共享方式既省內存又省時間。這樣的話,具有相似樣式的節點(比如兄弟節點)就只需要保存指向共享樣式結構對象的指針即可。而且,由于很多屬性都是繼承來的,所以祖先節點可以跟所有的子孫節點共享相同的樣式結構對象。

    優化改進

    上面所說的就是優化之前的樣式計算過程。

    這個過程中進行了很多計算工作。而且它不只是在第一個頁面加載的時候發生。它會在用戶與頁面進行交互的過程中反復的發生,懸停在元素上或者改變 DOM 結構,都會觸發樣式重算(Restyle)。

    也就是說,CSS 樣式計算是一個舉足輕重的待優化點。而且在過去的 20 年里,各個瀏覽器一直都在測試使用不同的策略來優化它。
    Stylo 充分吸收了來自不同引擎的優化策略,然后把它們結合在一起,從而創造出一個全新的超級引擎。

    下面讓我們來看看 Stylo 的實現細節。

    并行運行

    Servo 是一個實驗版的瀏覽器,Stylo 就是該項目的一部分。Servo 想把渲染頁面所需的所有工作都進行并行化。
    并行化具體指什么呢?

    一臺計算機就像一個大腦。其中有一個部分是專門進行邏輯思考的,叫做算術邏輯單元(Arithmetic Logic Unit, ALU)。在 ALU 附近,排列著一些短期記憶存儲單元,稱為寄存器(Register)。ALU 和寄存器都是一起放在在 CPU 內部的。當然也有用于長期記憶的存儲單元,稱為內存(RAM)。

    使用這種 CPU 的早期計算機在同一時間只能進行一種事情。
    不過在過去的十幾年里,CPU 已經進化到同時擁有多個 ALU 和寄存器組,具備了多個核心。
    這就意味著 CPU 可以一次進行多種事情,而且是同時進行的。

    Stylo 通過利用計算機的這種特性,把不同 DOM 節點的樣式計算過程分配到不同的計算核心當中。

    這看起來是一件很簡單的事情,只需要把 DOM 樹的不同分支分開來,然后交給不同的核心即可。但實際上做起來卻比想象的更加困難,其中一個原因就是 DOM 樹通常是不均勻的。這會導致有些核心做的工作會比其它的做得多很多。

    為了讓工作分配得更加均勻,Stylo 采用了一種稱為工作偷竊(Work Stealing)的技術。當處理一個 DOM 節點時,運行的代碼會把它的子節點分成一個或多個工作單元(Work Units)。這些工作單元會被添加到一個隊列中去。

    當某個核心把它的工作隊列都完成后,它會查看其它隊列中的工作單元,然后拿過來做。
    這樣的話,我們就可以把工作分配得更加均勻,而又不需要花費時間來遍歷 DOM 樹,也不需要事先就花費時間來計算該如何均勻地分配工作。

    在大多數的瀏覽器中,這種并行化工作做起來非常困難??偹苤⑿谢且粔K難啃的硬骨頭,而且 CSS 引擎非常復雜。同時, CSS 引擎還處于其他兩個最復雜部分: DOM 和布局的中間地帶。
    因此,這會非常容易引入 BUG ,而且并行化也會導致非常難以追查的 BUG,叫做數據競爭(Data Races)。我在另一篇文章中詳細介紹了這種類型錯誤,感興趣的可以參考下。

    如果你接受來自成百上千名工程師的代碼貢獻,你是如何做到平行編程而又無懼 BUG 的呢?這正是 Rust 的用武之地。

    在 Rust 中,你可以通過靜態檢查的方式來避免數據競爭。也就是說,你可以直接在代碼中就避免這種難以調試的錯誤。編譯器是不會讓你的代碼存在這樣的問題的。

    使用 Rust ,CSS 樣式計算就變成了所謂的完美并行問題,因為你基本上不用做什么就實現了并行化。這意味著我們的這個優化可以達到線性增長。如果你的機器有 4 個核心,那么你就擁有接近 4 被的性能增長。

    規則樹

    對于每個 DOM 節點,CSS 引擎需要遍歷所有的樣式規則來完成選擇器匹配。
    但是對于大多數節點來說,這種匹配規則并不是改變的太頻繁。
    比如,如果用戶把光標懸停在某個父元素上,那么匹配中該元素的樣式規則就可能改變了。我們也需要重新計算它的后代元素的樣式,以重新處理那些繼承屬性。當然,匹配中這些后代元素的規則也可能是不變的。

    如果我們能夠記錄哪些規則能夠匹配中這些后代元素,那是極好的,這樣我們就不需要對它們重新進行選擇器匹配。這就是我們從 Firefox 上一代 CSS 引擎中借鑒過來的規則樹(Rule Tree)的原理。

    CSS 引擎會經歷選擇器進行匹配的整個過程,然后按照特異性來排列它們,由此創建一個規則鏈表。

    該鏈表會被添加到規則樹中。

    CSS引擎會盡量使得規則樹的分支數量保持在最小值。為此,它會盡量復用已存在的規則分支。

    如果鏈表中的選擇器與已存在的分支相同,那么它將順著相同的路徑往下走。不過它可能最終會走到一個下一個規則不同的節點處,只有這個時候引擎才會新增一個分支。

    DOM 節點會取得指向這個規則最尾端節點的指針(這個例子中是 div#warning 規則)。而且,它的特異性最高的規則。

    在樣式重算時,CSS 引擎會進行一項快速檢查,以判斷對父元素的變更是否會影響匹配中子元素的規則。如果不影響,那么對于任何后代節點,引擎只需要順著后代節點保存的規則指針就可以找到對應規則分支。在規則樹中,只要順著樹向上遍歷到根節點就可以獲取所有匹配的樣式規則。也就是說,CSS 引擎完全跳過了選擇器匹配和特異性排列過程。

    這樣我們就減少了樣式重算過程的計算量。
    雖然如此,但是在樣式初始化時還是會耗費大量計算。假如有 10,000 個節點,仍然需要進行 10,000 次選擇器匹配。
    不過,不用擔心,我們還有另一種方式來優化它。

    樣式共享緩存

    對于一個擁有成千上萬個節點的頁面,其中有許多節點都會匹配中相同的樣式規則。
    舉例來說,對于一個很長的維基頁面,主要內容區的段落應該都是應用相同的樣式規則,因此也就有相同的計算樣式。

    如果這里不做優化的話,那么 CSS 引擎必須對每個段落都進行一次選擇器匹配和樣式計算。
    但是如果有一種方式能證明這些不同段落使用的是相同樣式的話,那么引擎就只需要做一次計算即可,然后其他段落節點都指向相同的計算樣式。

    這就是我們所說的樣式共享緩存(Style Sharing Cache),這種做法的靈感來自 Safari 和 Chrome 。
    當處理完一個節點之后,引擎會把計算樣式放進緩存。然后,在開始計算下一個節點的樣式之前,引擎會做一些檢查來判斷是否可以使用已緩存的樣式。

    這些檢查包括:

    兩個節點是否有相同的 id、class 等?如果是,那么它們可以匹配中相同的樣式規則。

    對于任何不是基于選擇器的樣式,比如內聯樣式,節點具有相同的樣式值么?如果是,那么繼承自父節點的屬性不會被覆蓋,或者以相同的方式被覆蓋。

    節點的父節點是否指向相同的計算樣式對象?如果是,那么繼承的樣式值則是一樣的。

    從樣式共享緩存被提出的一開始,這些檢查就已經應用了。
    不過,隨著 CSS 的發展,有許多其它小場景會導致樣式共享緩存的檢查方式失效。
    比如,如果一個 CSS 規則使用了 :first-child 選擇器,那么兩個段落元素時就可能會導致樣式不一致,即使上面的那些檢查都認為它們是相同的。

    在 WebKit 和 Blink 中,樣式共享緩存會忽略這些場景,并且不使用緩存。
    隨著越來越多的網站使用現代選擇器,樣式共享緩存的優化變得越來越雞肋,因此 Blink 團隊最終還是把它移除了。
    但是,事實證明樣式共享緩存還是有辦法跟上這些進化節奏的。

    在 Stylo 中,我們把記錄著所有這些現代選擇器并檢查他們是否能夠適用于 DOM 節點。然后,我們把檢查結果以 0 和 1 的方式存儲起來。如果兩個元素有相同的 0 和 1 ,那么我們就可以確定它們是匹配的。

    如果一個 DOM 節點可以使用已經計算的樣式緩存,那么引擎就可以直接跳過大量的計算過程。由于頁面中經常有大量的 DOM 節點擁有相同的樣式規則,所以樣式共享緩存不僅可以節省內存,同時也能加快計算過程。

    結論

    Stylo 是第一個從 Servo 遷移到 Firefox 的大型技術。
    在這個過程中,我們已經學到了很多關于如何把使用 Rust 編寫現代高性能代碼集成到 Firefox 核心。

    事不宜遲,趕緊下載 Firefox ,體驗極速吧!

  • 文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

    轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/113102.html

    相關文章

    • 圖說 WebAssembly(六):現狀與展望

      摘要:現狀年月日,主流的四大瀏覽器達成了共識并宣布的最小可行產品已經完成。更快的函數調用當前,在中調用函數比想象的要慢。直接操作目前,沒有任何方式能夠操作。這就導致了部分應用可能會因此而推遲發布時間。結束現如今已經相當快速。 本文是圖說 WebAssembly 系列文章的最后一篇。如果您還未閱讀之前的文章,建議您從第一篇入手。 現狀 2017 年 2 月 28 日,主流的四大瀏覽器達成了共識...

      clasnake 評論0 收藏0
    • 圖說 WebAssembly(二):JIT 編譯器

      摘要:編譯器優缺點與解釋器相比,編譯器有著相反的優缺點。它們為引擎新增了一個組件,稱為監視器,或者。優化編譯器會基于監視器記錄的代碼運行信息來作出一些判斷。通常來說,優化編譯器會使得代碼跑的更快。而這正是優化編譯器所做的優化之一。 本文是圖說 WebAssembly 系列文章的第二篇,如果你還沒閱讀其它的,建議您從第一篇開始。 JavaScript 的運行,一開始是很慢的,但是后面會變得越來...

      LuDongWei 評論0 收藏0
    • 圖說 WebAssembly(一):序言

      摘要:性能簡史在年,被創造出來時并不是沖著性能去的。而且在之后的十年發展中,它的性能一直是很低的。的引入成就了性能提升的一個轉折點,其執行速度比以往快了之多。性能提升也使得在全新的問題上使用成為可能?,F在,極可能是下一個性能轉折點。 你可能已經聽說 WebAssembly 代碼跑起來非???。但是你知道這是為什么嗎?在本系列文章中,我們將探究其原因。 何為 WebAssembly WebAss...

      codergarden 評論0 收藏0
    • 瀏覽器內核、JS 引擎、頁面呈現原理及其優化

      摘要:瀏覽器內核又叫渲染引擎,主要負責的解析,頁面布局渲染與復合層合成。頁面呈現原理規范定義了的詞法及語法文法。解析器使用和解析生成器從語法文件中自動生成解析器?;貞浺幌陆馕銎鞯慕榻B,創建一個自底向上的解析器,使用自頂向下解析器。 瀏覽器內核又叫渲染引擎,主要負責 HTML、CSS 的解析,頁面布局、渲染與復合層合成。瀏覽器內核的不同帶來的主要問題是對 CSS 的支持度與屬性表現差異。 we...

      wean 評論0 收藏0
    • 瀏覽器內核、JS 引擎、頁面呈現原理及其優化

      摘要:瀏覽器內核又叫渲染引擎,主要負責的解析,頁面布局渲染與復合層合成。頁面呈現原理規范定義了的詞法及語法文法。解析器使用和解析生成器從語法文件中自動生成解析器?;貞浺幌陆馕銎鞯慕榻B,創建一個自底向上的解析器,使用自頂向下解析器。 瀏覽器內核又叫渲染引擎,主要負責 HTML、CSS 的解析,頁面布局、渲染與復合層合成。瀏覽器內核的不同帶來的主要問題是對 CSS 的支持度與屬性表現差異。 we...

      zlyBear 評論0 收藏0

    發表評論

    0條評論

    最新活動
    閱讀需要支付1元查看
    <