簡介
如果您是會持續關注「瀏覽器運作方式」這類資訊的人,那麼您可能已經知道,最近有幾篇精彩的文章詳細介紹 Chrome 的 GPU 加速轉譯器/合成作業。首先,Chrome 中的加速轉譯:圖層模型一文提供了 Chrome 如何使用圖層概念繪製網頁的簡介;如要深入瞭解相關資訊,請參閱 Chrome 中的 GPU 加速合成一文,瞭解 Chrome 如何使用這些圖層和 GPU 來轉譯網頁。
哲學問題
我花了大量時間為 3D 目的編寫軟體算繪器,因此我認為,在繪製網頁時,某些 CSS 屬性應具有不同的效能。舉例來說,將小圖片算繪至螢幕上,與在任意形狀上繪製陰影的演算法作業完全不同。因此問題變成:不同的 CSS 屬性如何影響網頁的算繪權重?
我的目標是根據著色時間,將大量 CSS 屬性/值分類,以便瞭解哪些 CSS 屬性類型比其他類型更有效率。為此,我使用膠帶和泡泡糖編寫了一些自動化程式,嘗試在 CSS 繪製時間中加入數值可見度,運作方式如下:
- 產生一系列個別的 HTML 網頁,每個網頁都含有單一 DOM 元素,並附加一些 CSS 屬性變化。
- 執行自動化動作指令碼,針對每個網頁執行以下動作:
- 起 Chrome
- 載入網頁
- 為頁面產生 Skia Picture
- 透過 Skia Benchmark 執行每張 Skia 圖片,以取得時間
- 請查看所有時間,並驚嘆這些數字。(這部分很重要…)
透過這種設定,我們會產生一系列 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 Picture (*.SKP) 評估用於繪製網頁的 Skia 指令。為每個 HTML 檔案產生 SKP 檔案後,我們會執行另一個批次,透過 Skia Benchmark 應用程式 (由 Skia 原始碼建構) 推送 *.SKP 檔案,並記錄轉譯該網頁所需的平均時間。
評估資料
從這項資訊,我們現在可以粗略繪製一組 CSS 屬性所需的繪製時間。或者,我們可以開始依 CSS 資源的繪製成效進行排序。以下是使用 Chrome 27 開發人員版本繪製的大型圖表,顯示此程序的所有完整時間資料。請注意,隨著 Chrome 速度越來越快,所有資料都可能會有所變動。
每個垂直長條代表網頁的繪製時間,其中包含單一 CSS 屬性組合 (放大 100 倍;此圖表的真實比例值為 0.1.56 毫秒)。雖然有許多漂亮的線條,但在這種形式下,這些線條幾乎沒有用處;我們需要進行一些資料挖掘,才能找出有用的趨勢。
首先,我們發現某些 CSS 屬性比其他屬性更耗費渲染時間。舉例來說,在 DOM 元素上繪製陰影需要使用多重迴圈運算,並搭配樣條曲線和其他不便處理的項目,而這與不透明度相比,應更容易算繪。
其次,更有趣的是,CSS 屬性組合所需的繪製時間,可能比各個部分的總和還要長。從觀察者的角度來看,這有點奇怪,因為我們預期 A + B = C,而不是 2.2C。例如新增 box-shadow
和 border-radius-stroke
:
這裡最有趣的地方在於,這並非只是 box-shadow
屬性本身,而是特定值的排列組合。舉例來說,下方顯示 box-shadow : 50%
和 border-radius
的值變化組合。
根據資料顯示,這項問題會持續一段時間。有很多奇怪的組合,我的測試套件幾乎不會觸及這些組合;但仍有許多測試和組合可能會產生有趣的結果
找出網頁的算繪權重
開發人員可以追蹤網頁上每個元素的算繪時間,進而評估網頁算繪重量,以及這項重量對網站回應速度的影響。以下提供幾個開始評估的訣竅。
- 在 Chrome 開發人員工具中使用 Chrome 的連續繪圖模式,瞭解哪些 CSS 屬性會造成效能損失。
- 將 CSS 審查納入現有的程式碼審查程序,以便找出效能問題。請找出 CSS 中使用較耗資源的項目,例如漸層和陰影。請問自己是否真的需要這些內容?
- 如有疑問,請一律選擇效能較佳的選項。使用者可能不會記得欄位邊框的寬度,但他們會記得造訪網站時的感受。
結語
這項實驗最有趣的地方在於,Chrome 版本會持續變更時間,希望速度能越來越快;瀏覽器軟體是不斷變化的表面區域。今天速度緩慢的網站,明天可能就會變得快速。您可以從這篇文章中移除,避免將 box-shadow: 1px 2px 3px 4px
放在已含有 border-radius:5
的元素中。不過,更有價值的結論應該是 CSS 屬性會直接影響網頁繪製時間。