主頁 > 企業開發 > 記錄--瀏覽器渲染流程決議

記錄--瀏覽器渲染流程決議

2022-07-13 10:53:41 企業開發

這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助

大家可能經常會聽到 css 影片比 js影片性能更好這樣的論斷,或者是“硬體加速”,“層提升” 這樣的字眼;要了解這些內容就需要對瀏覽器的渲染流程有個大致的了解,本文就是我個人對這些內容的一個總結梳理

需要注意的是:

  1. 本文僅個人學習總結梳理,如有錯漏,望指正
  2. 本文以谷歌瀏覽器Blink內核為例
  3. 隨著谷歌瀏覽器的更新迭代,有些渲染流程或物件名詞可能發生變化(如, RenderObject 變成了 LayoutObject,RenderLayer 變成了 PaintLayer),查看相關檔案時需要注意檔案的時間

渲染流程

先來看下blink的一個大致渲染流程,圖源谷歌的一份共享幻燈片 Life of a Pixel ,它比較全面的闡述了瀏覽的渲染流程,非常值得一看,我們就借這張圖來梳理一遍

圖中分為 渲染行程(renderer process) 和 GPU行程(GPU process) 兩部分,其中渲染行程包含 主執行緒(main) 和 合成執行緒(impl)

我們可以借助谷歌開發工具的 performance 標簽查看是否執行了某些渲染流程步驟,我這里寫了一個簡單的html可以作為對比

<!DOCTYPE html>
<html lang="zh-cn">
?
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>transform demo</title>
</head>
<style>
  #normal {
    display: grid;
    place-items: end;
    width: 150px;
    height: 150px;
    background-color: pink;
  }
?
  #compositor {
    margin-top: 20px;
    display: grid;
    place-items: end;
    width: 150px;
    height: 150px;
    background-color: palegoldenrod;
  }
?
  #stacking {
    display: grid;
    place-items: end;
    width: 150px;
    height: 150px;
    position: absolute;
    z-index: -1;
    top: 240px;
    background-color: skyblue;
  }
?
  .active {
    animation: transformAni 2s both;
  }
?
  @keyframes transformAni {
    to {
      transform: translate(200px);
    }
  }
</style>
?
<body>
  <div id="compositor">Compositor Layers</div>
  <div style="display: flex; margin-top: 20px;">
    <div id="cssBtn" style="background-color:  palegoldenrod; width: 200px;">add css animation</div>
  </div>
?
  <div id="stacking">The Stacking Context</div>
  <div style="display: flex; margin-top: 220px;">
    <div id="jsBtn" style="background-color: skyblue; width: 200px;"> add js animation</div>
  </div>
?
  <script>
    const cssBtn = document.getElementById('cssBtn')
    const compositor = document.getElementById('compositor')
    cssBtn.addEventListener('click', () => {
      compositor.classList.add("active");
    })
?
    const jsBtn = document.getElementById('jsBtn')
    const stacking = document.getElementById('stacking')
    jsBtn.addEventListener('click', () => {
      setInterval(() => {
        stacking.style.left = `${stacking.getBoundingClientRect().left + 10}px`
      }, 100);
    })
?
  </script>
</body>
?
</html>

1. 構建DOM樹

對應頭圖中 DOM 節點,由于瀏覽器本身無法直接理解和使用html,所以需要將html轉換為瀏覽器能夠理解的DOM樹,也正是因此我們才能通過js控制dom節點

2. 樣式計算

對應頭圖中 style 節點,不僅是html,瀏覽器同樣無法直接讀懂我們寫的 css ,因此瀏覽器會將我們寫的 css 轉換成它能理解的 styleSheets ,同時計算每個 DOM 節點的樣式結果,包括將處理樣式的繼承覆寫,將 rem 等相對單位轉換成 px,將 margin: 8 這樣的縮寫,拆開決議成 margin-left: 8margin-top: 8 等具體的值,可以通過 computed 標簽查看,

3. 布局計算

對應頭圖中 layout 節點,這個階段也是我們很常聽到的 回流(reflow),重排,在上兩個階段結束后會生成一個儲存其計算結果的樹結構 LayoutObject Tree,在這個階段瀏覽器會遍歷 LayoutObject Tree 計算每個節點在頁面上具體的布局(比如是正常流布局,或是flex布局,哪個元素該放到哪個具體的像素位置上),計算文本實際寬高等;這一階段谷歌正在重構,目前輸入和輸出都混在 LayoutObject Tree 上,之后可能會將輸出部分抽離出來

4. 分層階段

對應頭圖中 comp.assign (compositing assignments) 節點,這個階段是我們獲取性能提升的關鍵,頁面上的元素,根據所處坐標空間(基本可以理解為層疊背景關系)不同等原因,會被劃分為不同的 PaintLayer,通過分層的方式保證頁面上元素以正確的順序層疊;在此基礎上,某些特殊的PaintLayer 會被提升為合成層(Compositing Layers),每個合成層擁有單獨的 GraphicsLayer , 而沒有被提升的 PaintLayer 則與其祖先元素共用同一個 GraphicsLayer.

它們間的對應關系如下圖

每個 GraphicsLayer 都有一個 GraphicsContextGraphicsContext 負責輸出該層的位圖,即每層代表一份位圖,GPU將位圖合成渲染到螢屏上也就是我們看到的頁面

我們可以通過開發者工具的 Layer 標簽看到 GraphicsLayer 的分層,劃分 PaintLayer 和 提升為 GraphicsLayer 的條件具體可見 無線性能優化:Composite (需要注意層重疊,層壓縮問題)

比如我上面的例子中,我給橙色的 div 加上了 will-change:transform 導致了層提升,而藍色的 div 與 document 共用一個 GraphicsLayer;我們還可以在 Details 標簽看到層提升的具體原因還有記憶體消耗 (tips: 層提升原因還可以看 safari 瀏覽器開發者工具的 layers ,會更加具體)

5. Pre-paint

這一階段主要有兩個任務,一是判斷與上一次paint階段(見下)相比有哪些內容需要被更新,二是構建 property trees

Paint invalidation which invalidates display items which need to be painted.

Builds paint property trees.

property treesproperty 是指 translation, scale 等需要大量計算的屬性,將這些屬性抽離出來單獨管理,避免父元素的變動導致其子元素上所有的屬性都有全部重新計算,具體見 How cc Works

6. paint

繪制階段,這一階段即我們常說的重繪階段,但這一階段并不是執行實際的頁面繪制,而是依據頁面內容的層疊順序生成 繪制任務串列,詳見 layer 工具,滾動滑輪可以重播繪制程序,可以觀察到,同一層疊背景關系情況下,先生成背景繪制任務,再生成元素內容繪制任務,再生成更高層級的層疊背景關系元素的繪制任務;

主執行緒的任務到這里基本結束,將繪制串列提交(commit)到合成執行緒

7. tiling

tiling 分塊,為 GPU光柵化做準備;光柵化是GPU根據繪制任務生成位圖,并將位圖儲存在記憶體中,大家可能聽過 CPU 光柵化的操作,這里參考一段 How cc Works 中文譯文

Chromium 目前實際支持三種不同的光柵化和合成的組合方式:軟體光柵化 + 軟體合成,軟體光柵化 + gpu 合成,gpu 光柵化 + gpu 合成,在移動平臺上,大部分設備和移動版網頁使用的都是 gpu 光柵化 + gpu 合成的渲染方式,理論上性能也最佳

由于這一操作需要消耗較多資源,為了減少資源消耗和使頁面更快呈現會將圖層進行分塊( tiles ),將圖塊作為光柵化的基本單位,同時優先對視口附近的圖塊進行光柵化

通過rendering 標簽,勾選 layer borders 可以看到分塊情況,橙線是不同的 layer 而 青綠色的線則劃分了圖塊

8. raster

這一步由GPU執行光柵化操作,之后的節點我沒再深入了解,大概是光柵化生成draw quads 命令,該命令會參考光柵化結果最后將內容展現在螢屏上

總結

最后我們分別錄制兩個影片的執行流程

js 影片

 

可以看到 js 影片在每次執行時會重排重繪,執行整個流程,上面橙紅色的那條前面有寫到 Layout Shift,即 布局提升,也就是我們說的強制重排,因為我們在 js 腳本里執行了 stacking.getBoundingClientRect().left 訪問元素位置,這就需要立刻重排來計算元素當前的位置

css影片

可以看到,css影片主執行緒上沒有進行重排重繪

梳理完整個流程,我們就能理解開頭提到的內容了,關鍵點就在于分層合成

“層提升” 即文中的 分層階段;

“硬體加速” 即 GPU加速,一些可能導致頁面大范圍重排重繪(如 translate影片),或需要大量簡單計算的任務(如 filter影片)都會導致層提升,將這部分任務交由GPU處理,將處理完后的結果再合成到頁面上;

而 css 影片性能更優的原因是:

  1. 避免了通過js訪問元素的位置資訊導致強制重排
  2. css影片元素移動時在合成層上進行,避免了頁面重排
  3. 合成由 GPU 行程控制,即使 js 阻塞主執行緒,css影片也能正常執行

層提升會加大記憶體消耗,加大移動端設備負擔,需要酌情使用

補充

will-change

上文我們的例子提到了 will-change 屬性,它的作用是提前告知瀏覽器可能變動的屬性,讓瀏覽器提前做好準備,提前進行相關計算等,它有以下取值

  • auto 讓瀏覽器自己猜哪些值會變動
  • scroll-position 表示滾動條位置可能發生變化或產生影片
  • contents 表示元素內容可能變動或產生影片
  • <custom-ident> 表示所有css屬性

基本上哪里的css屬性變化導致了頁面的卡頓都可以使用 will-change 優化

我們的例子中已經寫入了 will-change: transform ,因此瀏覽器一開始就幫我們做了層提升準備,所以橙色 div 一開始在頁面上就是分層的情況,而如果我們去掉這個屬性,觀察 layer 會發現橙色 div 一開始在頁面上并沒有層提升,只有在執行影片時才進行了層提升,影片結束后層提升又消失了

使用該屬性同樣要注意的是記憶體消耗問題,因為瀏覽器會提前進行優化計算并儲存計算結果,由于瀏覽器本身已經做了十足的性能優化,因此在頁面沒出現影片卡頓之前沒有必要使用該屬性,如果需要使用也盡量通過以下形式:

.will-change-parent:hover .will-change {
  will-change: transform;
}
.will-change {
  transition: transform 0.3s;
}
.will-change:hover {
  transform: scale(1.5);
}

當父元素 hover 時,給子元素加上 will-change,hover 失效則移出,既給了瀏覽器準備的時間,又避免了一直掛著該屬性帶來的資源消耗

requestAnimationFrame / requestIdleCallback

講到影片我們就順便提一嘴 requestAnimationFramerequestIdleCallback

我們看到的影片都是由螢屏快速播放一系列連貫的圖片組成,為了讓人眼感受不到卡頓,大多數螢屏的重繪頻率都是60Hz,即一秒鐘重繪六十次螢屏,每次重繪叫做一幀,一幀時間大約16.7ms,如果一幀的渲染時間超過這個數就會導致影片看起來出現了卡頓,一幀流程大致如下圖

requestAnimationFrame會在每一幀的渲染流程執行前都執行一次,因此使用js實作影片時,相比于 setInterval 實際執行時間的不確定性requestAnimationFrame 更加可靠;

requestIdleCallback 則是在每一幀結束前判斷是否有剩余時間,如果有則執行,無則不執行

本文轉載于:

https://juejin.cn/post/7116819495628472327

如果對您有所幫助,歡迎您點個關注,我會定時更新技術檔案,大家一起討論學習,一起進步,

 

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/498860.html

標籤:Html/Css

上一篇:sass的幾種輸出格式,你都知道嗎

下一篇:thymeleaf實作前后端資料交換

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 使用Django Rest framework搭建Blog

    在前面的Blog例子中我們使用的是GraphQL, 雖然GraphQL的使用處于上升趨勢,但是Rest API還是使用的更廣泛一些. 所以還是決定回到傳統的rest api framework上來, Django rest framework的官網上給了一個很好用的QuickStart, 我參考Qu ......

    uj5u.com 2023-04-20 08:17:54 more
  • 記錄-new Date() 我忍你很久了!

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 大家平時在開發的時候有沒被new Date()折磨過?就是它的諸多怪異的設定讓你每每用的時候,都可能不小心踩坑。造成程式意外出錯,卻一下子找不到問題出處,那叫一個煩透了…… 下面,我就列舉它的“四宗罪”及應用思考 可惡的四宗罪 1. Sa ......

    uj5u.com 2023-04-20 08:17:47 more
  • 使用Vue.js實作文字跑馬燈效果

    實作文字跑馬燈效果,首先用到 substring()截取 和 setInterval計時器 clearInterval()清除計時器 效果如下: 實作代碼如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta ......

    uj5u.com 2023-04-20 08:12:31 more
  • JavaScript 運算子

    JavaScript 運算子/運算子 在 JavaScript 中,有一些運算子可以使代碼更簡潔、易讀和高效。以下是一些常見的運算子: 1、可選鏈運算子(optional chaining operator) ?.是可選鏈運算子(optional chaining operator)。?. 可選鏈操 ......

    uj5u.com 2023-04-20 08:02:25 more
  • CSS—相對單位rem

    一、概述 rem是一個相對長度單位,它的單位長度取決于根標簽html的字體尺寸。rem即root em的意思,中文翻譯為根em。瀏覽器的文本尺寸一般默認為16px,即默認情況下: 1rem = 16px rem布局原理:根據CSS媒體查詢功能,更改根標簽的字體尺寸,實作rem單位隨螢屏尺寸的變化,如 ......

    uj5u.com 2023-04-20 08:02:21 more
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 08:01:50 more
  • 如何在 vue3 中使用 jsx/tsx?

    我們都知道,通常情況下我們使用 vue 大多都是用的 SFC(Signle File Component)單檔案組件模式,即一個組件就是一個檔案,但其實 Vue 也是支持使用 JSX 來撰寫組件的。這里不討論 SFC 和 JSX 的好壞,這個仁者見仁智者見智。本篇文章旨在帶領大家快速了解和使用 Vu ......

    uj5u.com 2023-04-20 08:01:37 more
  • 【Vue2.x原始碼系列06】計算屬性computed原理

    本章目標:計算屬性是如何實作的?計算屬性快取原理以及洋蔥模型的應用?在初始化Vue實體時,我們會給每個計算屬性都創建一個對應watcher,我們稱之為計算屬性watcher ......

    uj5u.com 2023-04-20 08:01:31 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:01:10 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:00:32 more