CSS 繪製時間和網頁轉譯權重

Colt McAnlis
Colt McAnlis

簡介

如果你是像瀏覽器運作方式這樣的老手,你應該已經知道我們近期有幾篇優質文章詳細說明 Chrome 的 GPU 加速轉譯器/複合操作。首先,Chrome 中的加速轉譯:圖層模型一文提供了 Chrome 如何使用圖層概念繪製網頁的簡介;如要深入瞭解相關資訊,請參閱 Chrome 中的 GPU 加速合成一文,瞭解 Chrome 如何使用這些圖層和 GPU 來轉譯網頁。

哲學問題

我花了大量時間為 3D 目的編寫軟體算繪器,因此我認為,在繪製網頁時,某些 CSS 屬性應具有不同的效能。舉例來說,將小圖片算繪至螢幕上,與在任意形狀上繪製陰影的演算法操作完全不同。因此問題變成:不同的 CSS 屬性如何影響網頁的算繪權重?

我的目標是依編輯時間將大量 CSS 屬性/值分類,以便我們瞭解哪些類型的 CSS 屬性成效較佳。為此,我使用膠帶和泡泡糖編寫了一些自動化程式,嘗試在 CSS 繪製時間中加入數值可見度,運作方式如下:

  • 產生一系列個別的 HTML 網頁,每個網頁都含有單一 DOM 元素,並附加一些 CSS 屬性變化。
  • 執行自動化動作指令碼,針對每個網頁執行以下動作:
  • 請查看所有時間,並驚嘆這些數字。(這部分很重要…)

透過這種設定,我們會產生一系列 HTML 頁面,每個頁面都包含 CSS 屬性和值的獨特排列組合;舉例來說,以下是兩個 HTML 檔案:

<style>
#example1 {
    background: url(foo.png) top left / 50% 60%;
    padding: 20px; 
    margin-top: 10px;
    margin-right: 20px; 
    text-align: center;
}
</style>
<div id="example1">WOAH</div>

另一個是複雜要求

<style>
#example1 {
    background-color:#eee;
    box-shadow: 1px 2px 3px 4px black;
    border-radius: 50%;
    background: radial-gradient(circle closest-corner, white, black);
    padding: 20px; 
    margin-top: 10px;
    margin-right: 20px; 
    text-align: center;
}
</style>
<div id="example1">WOAH</div>

以下是上一個範例的變化版本,我們只會變更 radial-gradient 值:

<style>
#example1 
{
    background-color:#eee;
    box-shadow: 1px 2px 3px 4px black;
    border-radius: 50%;
    background: radial-gradient(farthest-side, white, black);
    padding: 20px; 
    margin-top: 10px;
    margin-right: 20px; 
    text-align: center;
}
</style>
<div id="example1" style="padding: 20px; margin-top: 10px;margin-right: 20px; text-align: center;">WOAH</div>

接著,系統會將每個網頁載入 Chrome 的「最新」執行個體中 (確保重新載入頁面時不會發生任何過時狀態的過時時間偏誤),並採用 Skia 圖片 (*.SKP) 評估用來繪製網頁時使用的 Skia 指令。為每個 HTML 檔案產生 SKP 檔案後,我們會執行另一個批次,透過 Skia Benchmark 應用程式 (由 Skia 原始碼建構) 推送 *.SKP 檔案,並顯示轉譯該網頁所需的平均時間。

評估資料

從這項資訊,我們現在可以粗略繪製一組 CSS 屬性所需的繪製時間。或者,我們也可以按處理效果的 CSS 屬性開始堆疊排名。以下是使用 Chrome 27 開發人員版本繪製的大型圖表,顯示此程序的所有完整時間資料。請注意,隨著 Chrome 速度越來越快,所有資料都可能會有所變動。

測試中所有排列組合所需的時間

每個垂直長條代表網頁的繪製時間,其中包含單一 CSS 屬性組合 (放大 100 倍;此圖表的真實比例值為 0.1.56 毫秒)。數量相當可觀,但這個形式不太實用;我們需要進行資料探勘,才能找出有用的趨勢。

首先,我們發現某些 CSS 屬性比其他屬性更耗費渲染時間。舉例來說,在 DOM 元素上繪製陰影,需要使用多重迴圈運算,並搭配樣條曲線和其他類型的不便之處,而這與不透明度相比,應更容易算繪。

繪製僅含 1 個 CSS 屬性的元素所需的時間

其次,更有趣的是,CSS 屬性組合所需的繪製時間,可能比各個部分的總和還要長。從觀察者的角度來看,這有點奇怪,因為我們預期 A + B = C,而不是 2.2C。例如新增 box-shadowborder-radius-stroke

測試中所有排列組合所需的時間

這裡最有趣的地方在於,這並非只是 box-shadow 屬性本身,而是特定值的排列組合舉例來說,下方顯示 box-shadow : 50%border-radius 的值變化組合。

測試中所有排列組合所需的時間

根據資料顯示,這項問題會持續一段時間。有很多奇怪的組合,我的測試套件幾乎不會觸及所有組合;仍有大量測試和組合可產生有趣的結果

尋找網頁的轉譯權重

開發人員可以追蹤網頁上每個元素的算繪時間,進而評估網頁算繪重量,以及這項重量對網站回應速度的影響。以下提供幾個開始評估的訣竅:

  1. 在 Chrome 開發人員工具中使用 Chrome 的連續繪圖模式,瞭解哪些 CSS 屬性會造成效能損失。
  2. 將 CSS 評論納入現有的程式碼審查程序,以找出效能問題 在 CSS 中找出使用較昂貴的設施,例如漸層和陰影。請問自己是否真的需要這些內容?
  3. 如有疑問,請一律選擇效能較佳的選項。使用者可能不會記得欄位邊框的邊框寬度,但會記得造訪網站的感受。

結語

這項實驗最有趣的其中一項功能,就是每次 Chrome 版本 (希望速度更快,) 瀏覽器軟體的發展面也不斷變動。今天速度緩慢的網站,明天可能就會變得快速。您可以從這篇文章中移除,避免將 box-shadow: 1px 2px 3px 4px 放在已含有 border-radius:5 的元素中。不過,更有價值的結論應該是 CSS 屬性會直接影響網頁繪製時間。

參考資料