自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

看了就會(huì)的瀏覽器幀原理

系統(tǒng) 瀏覽器
本文會(huì)介紹瀏覽器中幀(Frame)的概念,它的流程是怎么樣的。至于寫這個(gè)文章的出發(fā)點(diǎn)在于,我好奇瀏覽器中像素工作流程是怎么樣的,什么時(shí)候開始的,最后的結(jié)果是什么。

[[394063]]

本文轉(zhuǎn)載自微信公眾號(hào)「TianTianUp」,作者TianTianUp。轉(zhuǎn)載本文請(qǐng)聯(lián)系TianTianUp公眾號(hào)。

前言

本文會(huì)介紹瀏覽器中幀(Frame)的概念,它的流程是怎么樣的。

至于寫這個(gè)文章的出發(fā)點(diǎn)在于,我好奇瀏覽器中像素工作流程是怎么樣的,什么時(shí)候開始的,最后的結(jié)果是什么。

基于這些好奇,查閱了些外文資料,本文提供了些參考,參考鏈接在文末。

緣由

在將幀的概念前,我們得從背景開始看起,也就是渲染頁面的這個(gè)過程,有哪些關(guān)鍵性的路徑呢。

五大關(guān)鍵渲染路徑

像素輸出到頁面,肯定經(jīng)歷了很多的過程,那我們作為前端工程師,工作中需要注意的點(diǎn)是哪些呢,這里給出參考:

渲染關(guān)鍵路徑

這五個(gè)主要的部分,應(yīng)該是我們值得去關(guān)注的,因?yàn)槲覀儞碛凶畲罂刂茩?quán)的部分。至于每一個(gè)過程具體是怎么樣的呢,不清楚的可以參考下圖:

每個(gè)階段任務(wù)

所以在這么一個(gè)像素的管道里,每部分都有可能造成卡頓,所以我們需要額外的關(guān)注這些,畢竟那一部分不當(dāng),都會(huì)開了不必要的性能開銷。

三種輸出方式

當(dāng)時(shí)我的疑問是: 難道每一幀都總是會(huì)經(jīng)過管道每個(gè)部分的處理嘛,其實(shí)不是這樣子的,從視覺的角度來說,管道針對(duì)指定幀的運(yùn)行通常有三種方式:

指定幀的運(yùn)行通常有三種方式

如果我們以第三種方式來更新視圖,也就是更改一個(gè)既不要布局也不要繪制的屬性,則瀏覽器將跳到只執(zhí)行合成。

跑個(gè)demo

為了更加具體的驗(yàn)證上述的過程,可以動(dòng)手跑一個(gè)demo,來驗(yàn)證一下。

demo地址:https://googlechrome.github.io/devtools-samples/jank/

主線程

我們添加多個(gè)dom元素進(jìn)行動(dòng)畫,效果更佳明顯,接著我們打開Performance,Record這個(gè)過程,我們需要關(guān)注的是Main選項(xiàng)卡,也就是主線程,我們?cè)诜糯罄锩娴腡ask,就有了下圖:

詳細(xì)的Task

經(jīng)歷的過程,也是很清楚看到,Update Layer Tree -->> Layout -->> Paint -->> Composite Layers。

如果你不是很清楚Performance中名稱的含義,可以參考下面這篇文章,點(diǎn)這里:

https://mp.weixin.qq.com/s/iodsGPWgYc97yWLb09Xk6A

接著,我們按下,Optimize按鈕,按照之前的流程走,Record后,發(fā)現(xiàn)不對(duì)勁,還是這樣子步驟,難道是哪里存在問題嘛,好奇的我,打開了Sources面板,然后就發(fā)現(xiàn)了:

未優(yōu)化的動(dòng)畫

它的源碼優(yōu)化動(dòng)畫,使用的是rAF,了解過的人一定不會(huì)陌生,你可以簡單的理解就是:按幀對(duì)網(wǎng)頁進(jìn)行重繪。這里就引出了幀的概念,后續(xù)會(huì)說明。

rAF的詳細(xì)介紹,后續(xù)會(huì)對(duì)它進(jìn)行梳理,可以持續(xù)關(guān)注。

 

如何避免回流與重繪

回到前面我們?cè)O(shè)想的點(diǎn),我們?nèi)绾尾拍鼙WC直接跳到合成過程,避免Layout以及Paint呢,當(dāng)然有,我們需要對(duì)app.js中的uppdate函數(shù)進(jìn)行改造,使用transform: translateX(0px); 做動(dòng)畫,做完update函數(shù)的處理邏輯后,我們?cè)俅蜶ecord一下:

優(yōu)化后的動(dòng)畫

從Task子任務(wù)中,我們可以發(fā)現(xiàn),Layout -->> Paint, 布局和繪制的過程跳過了。這也是為什么我們常說的需要避免回流與重繪。從主線程上來看,能夠完全的避免這些過程,避免了很多的運(yùn)算開銷。

這也是為什么經(jīng)??梢钥吹竭@樣子的建議:

  • 堅(jiān)持使用 transform 和 opacity 屬性更改來實(shí)現(xiàn)動(dòng)畫。
  • 使用 will-change 或 translateZ 提升移動(dòng)的元素。

至于使用will-change和translatez來提升圖層,這又是另外知識(shí)點(diǎn)了,這里就不張開了。

介紹到這里,我們已經(jīng)清楚的明白,避免回流和重繪的意義,那么我們提到的幀和rAF 與 渲染路徑有啥關(guān)系呢。

我做的第一件事情就是google,然后維基百科給出如下定義:

在視頻領(lǐng)域,電影、電視、數(shù)字視頻等可視為隨時(shí)間連續(xù)變換的許多張畫面,其中幀是指每一張畫面。

嗯,不是很好理解,知道我找到了這張圖,才解答了我的困惑:

frame

這就真的是一圖勝千言。

這個(gè)圖,你可以理解成就是像素放到屏幕的完整過程。你肯定對(duì)里面的一些關(guān)鍵信息很迷惑,這里作出一些解釋。

接下來大部分內(nèi)容都是翻譯的,沒有更多的總結(jié),感興趣可以看看原文。

PROCESSES(進(jìn)程)

映入眼簾的就是進(jìn)程:

  • Renderer Process: 渲染進(jìn)程。
    • 一個(gè)標(biāo)簽的周圍容器。
    • 它包含了多個(gè)線程,這些線程共同負(fù)責(zé)讓你的頁面出現(xiàn)在屏幕上的各個(gè)環(huán)節(jié)。
    • 這些線程是合成線程(Compositor)、圖塊柵格化線程(Tile Worker)和主線程。
  • GPU Process: GPU進(jìn)程。
    • 這是服務(wù)于所有標(biāo)簽和周圍瀏覽器進(jìn)程的單一進(jìn)程。
    • 當(dāng)幀被提交時(shí),GPU進(jìn)程將上傳任何磁貼和其他數(shù)據(jù)(如四維頂點(diǎn)和矩陣)到GPU,以便實(shí)際將像素推送到屏幕上。
    • GPU進(jìn)程包含一個(gè)單一的線程,稱為GPU線程,實(shí)際完成工作。

RENDERER PROCESS THREADS(渲染進(jìn)程中的線程)

現(xiàn)在我們來看看Renderer Process中的線程。

  • Compositor Thread(合成線程):
    • 這是第一個(gè)被告知vsync事件的線程(這是操作系統(tǒng)告訴瀏覽器制作新幀的方式)。
    • 它還將接收任何輸入事件。
    • 如果可以的話,合成器線程將避免進(jìn)入主線程,并將嘗試將輸入(比如說--滾動(dòng)甩動(dòng))轉(zhuǎn)換為屏幕上的運(yùn)動(dòng)。它將通過更新圖層位置并通過GPU線程直接將幀提交給GPU來實(shí)現(xiàn)。
    • 如果因?yàn)檩斎胧录幚沓绦蚧蚱渌曈X工作而無法做到這一點(diǎn),那么就需要使用主線程。
  • Main Thread(主線程):
    • 這是瀏覽器執(zhí)行我們都知道和喜歡的任務(wù)的地方。JavaScript、樣式、布局和繪畫。(在未來的Houdini中,這種情況會(huì)有所改變,我們將能夠在Compositor線程中運(yùn)行一些代碼。)
    • 這個(gè)線程贏得了 "最有可能導(dǎo)致jank "的獎(jiǎng)項(xiàng),主要是因?yàn)檫@里有很多東西在運(yùn)行。(jank值得是頁面抖動(dòng))
  • Compositor Tile Worker(s) (合成圖塊柵格化線程):
    • 由合成線程派生的一個(gè)或多個(gè)線程,用于處理柵格化任務(wù)。我們稍后再討論。

在很多方面,你應(yīng)該把Compositor線程視為 "大老板"。雖然它不運(yùn)行JavaScript、Layout、Paint或其他任何東西,但它是完全負(fù)責(zé)啟動(dòng)主線程工作的線程,然后將幀運(yùn)送到屏幕上。如果它不需要等待輸入事件處理程序,它就可以在等待主線程完成工作的同時(shí)運(yùn)送幀。

你也可以想象Service Workers和Web Workers生活在這個(gè)過程中,不過我沒有把他們包括在內(nèi),因?yàn)檫@讓事情變得更加復(fù)雜。

THE FLOW OF THINGS(主線程流程)

讓我們成主線程開始吧。

主線程

讓我們一步步走過這個(gè)流程,從vsync到像素,并談?wù)勗谑录?"全胖 "版本中事情是如何進(jìn)行的。值得記住的是,瀏覽器不需要執(zhí)行所有這些步驟,這取決于什么是必要的。例如,如果沒有新的HTML要解析,那么解析HTML就不會(huì)啟動(dòng)。事實(shí)上,很多時(shí)候,提高性能的最好方法就是簡單地消除部分流程被啟動(dòng)的必要性!

同樣值得注意的是,樣式和布局下的紅色箭頭似乎指向了 requestAnimationFrame。在你的代碼中完全有可能意外地觸發(fā)這兩者。這就是所謂的強(qiáng)制同步布局(或樣式,視情況而定),它通常對(duì)性能不利。

Frame Start(開始新的一幀):

垂直同步信號(hào)觸發(fā),開始渲染新的一幀圖像。

Input event handlers (輸入事件的處理)。

-輸入數(shù)據(jù)從合成器線程傳遞給主線程上的任何輸入事件處理程序。

所有的輸入事件處理程序(觸摸移動(dòng)、滾動(dòng)、點(diǎn)擊)都應(yīng)該首先啟動(dòng),每幀一次,但情況不一定如此。

調(diào)度器會(huì)做出最大努力的嘗試,其成功率在不同的操作系統(tǒng)中有所不同。在用戶交互和事件進(jìn)入主線程處理之間也有一些延遲。

requestAnimationFrame:

這是對(duì)屏幕進(jìn)行視覺更新的理想位置,因?yàn)槟阌行迈r的輸入數(shù)據(jù),而且這是你要得到的最接近vsync的地方。

其他的視覺任務(wù),比如樣式計(jì)算,都是在這個(gè)任務(wù)之后進(jìn)行的,所以它的理想位置是突變?cè)亍?/p>

如果你突變--比如說--100個(gè)類,這不會(huì)導(dǎo)致100個(gè)樣式計(jì)算;它們將被分批處理,并在后面處理。唯一需要注意的是,你不要查詢?nèi)魏斡?jì)算過的樣式或布局屬性(比如el.style.backgroundImage或el.style.offsetWidth)。

如果你這樣做,你會(huì)把重新計(jì)算的樣式、布局或兩者都向前帶,導(dǎo)致強(qiáng)制的同步布局,或者更糟糕的是,布局打亂。

Parse HTML (解析 HTML):

任何新添加的HTML都會(huì)被處理,并創(chuàng)建DOM元素。

在頁面加載過程中或appendChild等操作后,你可能會(huì)看到更多的這種情況。

Recalc Styles(重新計(jì)算樣式):

樣式是為任何新添加或突變的東西計(jì)算的,這可能是整個(gè)樹,也可能是范圍,這取決于改變了什么。

這可能是整個(gè)樹,也可能是范圍縮小,這取決于改變了什么。

例如,改變主體上的類可能影響深遠(yuǎn),但值得注意的是,瀏覽器已經(jīng)非常聰明地自動(dòng)限制了樣式計(jì)算的范圍。

Layout(繪制):

計(jì)算每個(gè)可見元素的幾何信息(每個(gè)元素的位置和大小)。它通常對(duì)整個(gè)文檔進(jìn)行計(jì)算,通常使計(jì)算成本與DOM大小成正比。

Update Layer Tree(更新圖層樹):

創(chuàng)建疊加上下文和深度排序元素的過程。

Paint:

這是兩部分過程中的第一部分:繪制是記錄任何新元素或視覺上有變化的元素的繪制調(diào)用(在這里填充一個(gè)矩形,在那里寫文字)。

第二部分是光柵化(見下文),在這里執(zhí)行繪圖調(diào)用,并填充紋理。這一部分是對(duì)繪制調(diào)用的記錄,通常比光柵化快得多,但這兩部分通常統(tǒng)稱為 "繪畫"。

Composite(合成):

計(jì)算出圖層和瓷磚的信息,并傳回給合成器線程來處理。

這將會(huì)考慮到,除其他事項(xiàng)外,像will-change,重疊元素,以及任何硬件加速的canvases。

Raster Scheduled (柵格化規(guī)劃)and Rasterize(柵格化):

現(xiàn)在會(huì)執(zhí)行在Paint任務(wù)中記錄的繪制調(diào)用。這是在Compositor Tile Workers中完成的,其數(shù)量取決于平臺(tái)和設(shè)備能力。

例如,在Android上,你通常會(huì)發(fā)現(xiàn)一個(gè)Worker,在桌面上,你有時(shí)可以找到四個(gè)。柵格化是以圖層為單位進(jìn)行的,每個(gè)圖層都是由瓷磚組成的。

Frame End(幀結(jié)束):

當(dāng)各個(gè)圖層的磁貼都柵格化后,任何新的磁貼都會(huì)和輸入數(shù)據(jù)(可能在事件處理程序中被改變)一起提交給GPU線程。

Frame Ships(發(fā)送幀):

最后,但絕不是最不重要的,磁貼由GPU線程上傳至GPU。GPU使用四邊形和矩陣(所有常見的GL好東西)將磁貼繪制到屏幕上。

大致上,整個(gè)的過程就是上述。

requestIdleCallback

要說這個(gè)的話,我們得拿requestAnimationFrame來類比,requestAnimationFrame是在重新渲染屏幕之前執(zhí)行的,上面提到的rAF,當(dāng)時(shí)做的就是優(yōu)化動(dòng)畫,所以很適合做動(dòng)畫。

requestIdleCallback你通過主線程里面中的Task去查找的話,會(huì)發(fā)現(xiàn)它是在渲染屏幕之后執(zhí)行,通過查閱文章發(fā)現(xiàn),一般會(huì)看瀏覽器是否空閑。

【責(zé)任編輯:武曉燕 TEL:(010)68476606】

 

 

責(zé)任編輯:武曉燕 來源: TianTianUp
相關(guān)推薦

2020-11-06 15:20:45

瀏覽器前端架構(gòu)

2013-05-23 16:01:56

瀏覽器

2013-06-14 13:56:29

瀏覽器渲染原理

2019-01-03 13:09:58

瀏覽器緩存原理

2020-03-12 11:29:51

JavaScript瀏覽器語言

2022-07-12 08:27:18

Zadig開源

2010-04-05 21:57:14

Netscape瀏覽器

2012-02-01 13:42:19

2022-08-30 09:01:11

瀏覽器渲染前端

2018-11-30 09:00:19

html5cssjavascript

2012-03-20 11:41:18

海豚瀏覽器

2012-03-20 11:31:58

移動(dòng)瀏覽器

2012-03-19 17:25:22

2021-12-09 07:54:19

瀏覽器引擎編譯

2012-03-20 11:07:08

2010-12-21 10:11:35

手機(jī)瀏覽器

2013-01-14 10:58:51

傲游云瀏覽器

2012-06-21 15:38:02

獵豹瀏覽器

2012-03-19 17:17:00

移動(dòng)瀏覽器歐朋

2012-03-20 11:22:02

QQ手機(jī)瀏覽器
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)