小方三防按:本文作者 被單,原載于?凹凸實驗室,小方三防(公眾號:小方三防)獲授權轉載。

一篇文章為你詳解什么是 GPU 加速-小方三防

眾所周知,網頁不僅應該被快速加載,同時還應該流暢運行,比如快速響應的交互,如絲般順滑的動畫……

一. GPU 加速能做什么?

首先我們要了解什么是 16ms 優化

  • 大多數設備的刷新頻率是 60 次/秒,(1000/60 = 16.6ms)也就說是瀏覽器對每一幀畫面的渲染工作要在 16ms 內完成,超出這個時間,頁面的渲染就會出現卡頓現象,影響用戶體驗。

  • 瀏覽器在一幀里面,會依次執行以下這些動作。減少或者避免 layout,paint 可以讓頁面不卡頓,動畫效果更加流暢。

一篇文章為你詳解什么是 GPU 加速-小方三防

1. JavaScript:JavaScript 實現動畫效果,DOM 元素操作等。

2. Style(計算樣式):確定每個 DOM 元素應該應用什么 CSS 規則。

3. Layout(布局):計算每個 DOM 元素在zui終屏幕上顯示的大小和位置。由于 web 頁面的元素布局是相對的,所以其中任意一個元素的位置發生變化,都會聯動的引起其他元素發生變化,這個過程叫 reflow。

4. Paint(繪制):在多個層上繪制 DOM 元素的的文字、顏色、圖像、邊框和陰影等。

5. Composite(渲染層合并):按照合理的順序合并圖層然后顯示到屏幕上。

利用 GPU 加速優先使用渲染層合并屬性,避免 layout,paint。

一篇文章為你詳解什么是 GPU 加速-小方三防

從上圖可以看出,可以通過改變元素的 transform 實現移動,伸縮變換而非改變物體的 left,top,width,height 避免 layout,paint。讓動畫效果更加流暢。

一篇文章為你詳解什么是 GPU 加速-小方三防

優化

一篇文章為你詳解什么是 GPU 加速-小方三防

二. GPU 是什么,如何用 Chrome devtools 進行分析 debug?

瀏覽器渲染一個頁面大致是按照下面這個步驟執行。

1. 獲取 DOM 并將其分割為多個層(RenderLayer)

2. 將每個層柵格化,并獨立的繪制進位圖中

3. 將這些位圖作為紋理上傳至 GPU

4. 復合多個層來生成zui終的屏幕圖像(終ji layer )。

Chrome 開啟查看 renderlayer

一篇文章為你詳解什么是 GPU 加速-小方三防

按上面的步驟之后,即可看到

一篇文章為你詳解什么是 GPU 加速-小方三防

1. 黃色邊框:有動畫 3d 變換的元素,表示放到了一個新的復合層(composited layer)中渲染

2. 藍色的柵格:這些分塊可以看作是比層更低一級的單位,這些區域就是 RenderLayer
打開一個頁面,如果該頁面的黃色邊框很多,那么肯定要查看一下原因了

Chrome 查看 layer

  • 打開 timeline 進行錄制,選中 timeline 的某一幀,然后選擇下面的 layer ,可以左右拖動該模塊出現 3d。
    我們可以看到一個頁面實際是像下面一樣組成的

一篇文章為你詳解什么是 GPU 加速-小方三防

  • 從上圖不難理解,雖然我們zui終在瀏覽器上看到的只是一個復印版,即zui終只有一個層。類似于PhotoShop軟件中的“圖層”概念,zui后合并所有可視圖層,輸出一張圖片到屏幕上。但實際上一些dom會因為一些規則被提升成獨立的層(開啟 GPU 加速),一旦被獨立出來之后,便不會再影響其他dom的布局,因為它改變之后,只是“貼上”了頁面。

根據這個優點,我們可以把頁面中一些布局經常變換的dom(動畫)提升到獨立的層。那么,瀏覽器在之后的 16ms 中,只需進行下面的幾個步驟。

一篇文章為你詳解什么是 GPU 加速-小方三防

三. 如何開啟 GPU 加速?

目前下面這些因素都會引起Chrome創建合成層:

1. 3D 或透視變換(perspective,transform) CSS 屬性

2. 使用加速視頻解碼的video元素

3. 擁有 3D (WebGL) 上下文或加速的 2D 上下文的 canvas 元素

4. 混合插件(如 Flash)

5. 對自己的 opacity 做 CSS 動畫或使用一個動畫 webkit 變換的元素

6. 擁有加速 CSS 過濾器的元素

7. 元素A有一個 z-index 比自己小的元素B,且元素B是一個合成層(換句話說就是該元素在復合層上面渲染),則元素A會提升為合成層。

上面7點都非常容易理解,在日常開發中,zui容易出現問題的是第7點

四. GPU 加速隱藏的坑–隱式合成
  • 元素A有一個 z-index 比自己小的元素B,且元素B是一個合成層(換句話說就是該元素在復合層上面渲染)

拿實際項目舉個栗子,我們按照上面的步驟開啟 layer borders

一篇文章為你詳解什么是 GPU 加速-小方三防

尚未給上圖右手添加高層級的 z-index 時,整個頁面在移動端打開后閃退。而添加了 z-index 之后,頁面正常顯示,不閃退了。
仔細看上面的 gif ,僅僅改變了 z-index ,就會改變大批數量的層(黃色邊框)

為什么 z-index 力量這么大?

我們來看一個栗子,B 在做動畫,理所當然把B提到單獨的合成層。減少重繪。

一篇文章為你詳解什么是 GPU 加速-小方三防

按照上圖,我們遇到一個邏輯問題,元素B應該在單獨的合成層上,并且屏幕的zui終圖像應該在 GPU 上組成。但是A元素在B元素的頂部,我們沒有指定提升A元素自身層級的東西。那么瀏覽器會做什么?它將強制為元素A創建一個新的合成圖層。
這樣,A和B都被提升到單獨的復合層。
因此,使用 GPU 加速提升動畫性能時,zui好給當前動畫元素增加一個高一點的 z-index 屬性,人為干擾復合層的排序,可以有效減少 Chrome 創建不必要的復合層,提升渲染性能。

注意:GPU 不僅需要發送渲染層圖像到 GPU ,而且還需存儲它們,以便稍后在動畫中重用。別盲目創建渲染層,一定要分析其實際性能表現。因為創建渲染層是有代價的,每創建一個新的渲染層,就意味著新的內存分配和更復雜的層的管理。對于使用移動設備的用戶來說是很坑的。移動設備沒有臺式機那么多的內存。過多的 GPU 加速會引起頁面卡頓甚至閃退。

找到 layers,點擊當前層,在右邊查看占用的 memory(內存)

一篇文章為你詳解什么是 GPU 加速-小方三防一篇文章為你詳解什么是 GPU 加速-小方三防

總結

整篇文章介紹了下面幾個部分

● GPU 加速能做什么

● GPU 是什么,如何用 Chrome devtools 進行分析 debug?

● 如何開啟 GPU 加速?

● GPU 加速隱藏的坑–隱式合成

參考:

http://www.jianshu.com/p/a32b890c29b1?

http://div.io/topic/1348?

小方三防相關閱讀:

黃仁勛親自撰文懟上 TPU:P40速度比你快 2 倍,帶寬是你的 10 倍

谷歌硬件工程師揭秘,TPU為何會比CPU、GPU快30倍?

小方三防版權文章,未經授權禁止轉載。詳情見轉載須知。

一篇文章為你詳解什么是 GPU 加速-小方三防