瀏覽器層合成與頁面渲染優(yōu)化

這是瀏覽器渲染引擎的處理過程:
image.png
1.接收到文檔后午绳,渲染引擎會對HTML文檔進(jìn)行解析生成DOM樹、對CSS文件進(jìn)行解析生成CSSOM樹映之;
2.同時(shí)執(zhí)行頁面中的JavaScript代碼拦焚;
3.最終根據(jù)DOM樹和CSSOM樹,計(jì)算樣式(Caluclate Style)生成渲染樹杠输,【渲染樹中赎败,只會包含即將顯示在頁面中的元素及其樣式信息(如head元素、display為hidden的元素就不會包含在渲染樹中)】抬伺;
4.根據(jù)渲染樹需要進(jìn)行布局(layout)來計(jì)算每個(gè)元素在頁面上的位置螟够;
5.接下來渲染引擎開始進(jìn)行繪制(paint),這一步分為若干階段:
5.1 根據(jù)渲染樹將每層(layer)的各個(gè)元素繪制
5.2然后將繪制出的若干連續(xù)圖像進(jìn)行柵格化(Rasterization)峡钓,最后將柵格化后的圖像合成(composite)為要顯示在屏幕上的圖像妓笙。
5.3對每一層的繪制是由瀏覽器來完成的;最后的合成是由GPU來完成能岩;而柵格化過程取決于瀏覽器的設(shè)置寞宫,chrome默認(rèn)開啟GPU柵格化,否則由CPU進(jìn)行拉鹃。
當(dāng)首次將DOM樹構(gòu)建完成后辈赋,每次頁面發(fā)生改變時(shí)進(jìn)行進(jìn)行的主要流程為:

javascript -->style-->;ayout -->paint -->compsite

其中CSS動畫不會調(diào)用JavaScript,我們知道膏燕,在渲染中主要消耗時(shí)間的是Layout/Reflow和Paint/Repaint的過程钥屈,因此要盡量避免和減少這兩個(gè)階段的時(shí)間。

cpu 和 gpu 的區(qū)別

cpu 是通用的坝辫,能夠執(zhí)行各種邏輯和運(yùn)算篷就,而 gpu 則是主要是用于并行計(jì)算大批量的重復(fù)任務(wù),不能處理復(fù)雜邏輯近忙。

cpu 中控制器和緩存占據(jù)了很大一部分竭业,而 gpu 中這兩部分則很少智润,但是有更多的核心用于計(jì)算。

兩者對比的話未辆,cpu 相當(dāng)于一個(gè)大學(xué)生窟绷,能夠解決各種難題,但是計(jì)算 1 萬個(gè)加法就沒那么快咐柜,而 gpu 就像一幫小學(xué)生兼蜈,解決不了難題,但是計(jì)算加法這種就很快炕桨,因?yàn)槿硕唷?/p>

也就是說如果邏輯復(fù)雜饭尝,那么只能用 cpu,如果只是計(jì)算量大献宫,并且每個(gè)計(jì)算都比較重復(fù),那就比較適合 gpu实撒。

3d 的渲染中有大量這種重復(fù)卻簡單的計(jì)算姊途,比如頂點(diǎn)數(shù)據(jù)和光柵化的像素?cái)?shù)據(jù),通過 gpu 就可以并發(fā)的一次計(jì)算成百上千個(gè)知态。

瀏覽器在處理下面的 css 的時(shí)候捷兰,會使用 gpu 渲染:

transform 、opacity 负敏、filter贡茅、 will-change
瀏覽器是把內(nèi)容分到不同的圖層分別渲染的,最后合并到一起其做,而觸發(fā) gpu 渲染會新建一個(gè)圖層顶考,把該元素樣式的計(jì)算交給 gpu。

opacity 需要改變每個(gè)像素的值妖泄,符合重復(fù)且大量的特點(diǎn)驹沿,會新建圖層,交給 gpu 渲染蹈胡。transform 是動畫渊季,每個(gè)樣式值的計(jì)算也符合重復(fù)且大量的特點(diǎn),也默認(rèn)會使用 gpu 加速罚渐。同理 fiter 也是一樣
却汉。
這里要注意的是 gpu 硬件加速是需要新建圖層的,而把該元素移動到新圖層是個(gè)耗時(shí)操作荷并,界面可能會閃一下合砂,所以最好提前做。will-change 就是提前告訴瀏覽器在一開始就把元素放到新的圖層璧坟,方便后面用 gpu 渲染的時(shí)候既穆,不需要做圖層的新建赎懦。

當(dāng)然,有的時(shí)候我們想強(qiáng)制觸發(fā)硬件渲染幻工,就可以通過上面的屬性励两,比如

will-change: transform; 
transform:translate3d(0, 0, 0);

SVG圖表動畫性能的優(yōu)化

對于一般的HTML的元素,遵循上述的方法就可以了囊颅,但有一些大屏中的圖表是使用SVG元素來繪制的当悔,由于并不是標(biāo)準(zhǔn)的DOM元素,Chrome并不能支持SVG元素的硬件加速踢代,即使設(shè)置了transform盲憎、will-change等屬性,單個(gè)的SVG元素也不能作為單獨(dú)的層進(jìn)行繪制胳挎。

對于有多個(gè)圖表的頁面饼疙,其中只有一個(gè)圖表有動畫,在動畫過程中慕爬,如果只有一個(gè)圖層窑眯,那么需要將整個(gè)圖層進(jìn)行重繪,雖然現(xiàn)在Chrome已經(jīng)可以智能選擇最小的重繪區(qū)域進(jìn)行增量繪制医窿,但當(dāng)圖層較大時(shí)這樣的判斷也會造成一定的開銷磅甩。因此可以考慮將有動畫的圖標(biāo)單獨(dú)放在一個(gè)圖層中,其他沒有動畫的圖表和頁面是的其他元素仍然和背景在一個(gè)圖層中姥卢。

在實(shí)際使用中卷要,可以在某張圖表需要動畫時(shí),設(shè)置SVG標(biāo)簽的will-change屬性独榴,將SVG元素提升到獨(dú)立的層僧叉,來減少動畫繪制時(shí)間;而圖表沒有動畫時(shí)則不需要特別處理括眠,避免過度繪制造成的內(nèi)存占用增加和圖層傳輸彪标、合成時(shí)間的增加。

一些優(yōu)化建議

1掷豺、動畫使用 transform 實(shí)現(xiàn)

對于一些體驗(yàn)要求較高的關(guān)鍵動畫捞烟,比如一些交互復(fù)雜的玩法頁面,存在持續(xù)變化位置的 animation 元素当船,我們最好是使用 transform 來實(shí)現(xiàn)而不是通過改變 left/top 的方式题画。這樣做的原因是,如果使用 left/top 來實(shí)現(xiàn)位置變化德频,animation 節(jié)點(diǎn)和 Document 將被放到了同一個(gè) GraphicsLayer 中進(jìn)行渲染苍息,持續(xù)的動畫效果將導(dǎo)致整個(gè) Document 不斷地執(zhí)行重繪,而使用 transform 的話,能夠讓 animation 節(jié)點(diǎn)被放置到一個(gè)獨(dú)立合成層中進(jìn)行渲染繪制竞思,動畫發(fā)生時(shí)不會影響到其它層表谊。并且另一方面,動畫會完全運(yùn)行在 GPU 上盖喷,相比起 CPU 處理圖層后再發(fā)送給顯卡進(jìn)行顯示繪制來說爆办,這樣的動畫往往更加流暢。

2课梳、減少隱式合成

雖然隱式合成從根本上來說是為了保證正確的圖層重疊順序距辆,但具體到實(shí)際開發(fā)中,隱式合成很容易就導(dǎo)致一些無意義的合成層生成暮刃,歸根結(jié)底其實(shí)就要求我們在開發(fā)時(shí)約束自己的布局習(xí)慣跨算,避免踩坑。

我們在平時(shí)開發(fā)中不注意可能造成頁面生成了過多的合成層椭懊,之前有一個(gè)項(xiàng)目诸蚕,在pc端查看是存在明顯卡頓,利用 Chrome Devtools 分析之后發(fā)現(xiàn)灾搏,頁面里邊存在的一個(gè)帶動畫 transform 的 button 按鈕挫望,提升為了合成層,動畫交疊的不確定性使得頁面內(nèi)其他 z-index 大于它但其實(shí)并沒有交疊的節(jié)點(diǎn)也都全部提升為了合成層(這個(gè)原因真的好坑)狂窑。

這個(gè)時(shí)候我們只需要把這個(gè)動畫節(jié)點(diǎn)的 z-index 屬性值設(shè)置得大一些,讓層疊順序高過于頁面其他無關(guān)節(jié)點(diǎn)就行桑腮。當(dāng)然并不是盲目地設(shè)置 z-index 就能避免泉哈,有時(shí)候 z-index 也還是會導(dǎo)致隱式合成,這個(gè)時(shí)候可以試著調(diào)整一下文檔中節(jié)點(diǎn)的先后順序直接讓后邊的節(jié)點(diǎn)來覆蓋前邊的節(jié)點(diǎn)破讨,而不用 z-index 來調(diào)整重疊關(guān)系丛晦。方法不是唯一的,具體方式還是得根據(jù)不同的頁面具體分析提陶。

改善后的頁面效果如下烫沙,可以看到相比優(yōu)化前,我們消除了很多無意義的合成層隙笆。

3锌蓄、減小合成層的尺寸

舉個(gè)簡單的例子,分別畫兩個(gè)尺寸一樣的 div撑柔,但實(shí)現(xiàn)方式有點(diǎn)差別:一個(gè)直接設(shè)置尺寸 100x100瘸爽,另一個(gè)設(shè)置尺寸 10x10,然后通過 scale 放大 10 倍铅忿,并且我們讓這兩個(gè) div 都提升為合成層:

<style>
  .bottom, .top {
    position: absolute;
    will-change: transform;
  }
  .bottom {
    width: 100px;
    height: 100px;
    top: 20px;
    left: 20px;
    z-index: 3;
    background: rosybrown;
  }
  .top {
    width: 10px;
    height: 10px;
    transform: scale(10);
    top: 200px;
    left: 200px;
    z-index: 5;
    background: indianred;
  }
</style>
<body>
  <div class="bottom"></div>
  <div class="top"></div>
</body>

利用 Chrome Devtools 查看這兩個(gè)合成層的內(nèi)存占用后發(fā)現(xiàn)剪决,.bottom 內(nèi)存占用是 39.1 KB,而 .top 是 400 B,差距十分明顯柑潦。這是因?yàn)?.top 是合成層享言,transform 位于的 Composite 階段,現(xiàn)在完全在 GPU 上執(zhí)行渗鬼。因此對于一些純色圖層來說览露,我們可以使用 width 和 height 屬性減小合成層的物理尺寸,然后再用 transform: scale(…) 放大乍钻,這樣一來可以極大地減少層合成帶來的內(nèi)存消耗肛循。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市银择,隨后出現(xiàn)的幾起案子多糠,更是在濱河造成了極大的恐慌,老刑警劉巖浩考,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件夹孔,死亡現(xiàn)場離奇詭異,居然都是意外死亡析孽,警方通過查閱死者的電腦和手機(jī)搭伤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來袜瞬,“玉大人怜俐,你說我怎么就攤上這事〉擞龋” “怎么了拍鲤?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長汞扎。 經(jīng)常有香客問我季稳,道長,這世上最難降的妖魔是什么澈魄? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任景鼠,我火速辦了婚禮,結(jié)果婚禮上痹扇,老公的妹妹穿的比我還像新娘铛漓。我一直安慰自己儒飒,他們只是感情好查邢,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著阱洪,像睡著了一般芬迄。 火紅的嫁衣襯著肌膚如雪问顷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機(jī)與錄音杜窄,去河邊找鬼肠骆。 笑死,一個(gè)胖子當(dāng)著我的面吹牛塞耕,可吹牛的內(nèi)容都是我干的蚀腿。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼扫外,長吁一口氣:“原來是場噩夢啊……” “哼莉钙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起筛谚,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤磁玉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后驾讲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蚊伞,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年吮铭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了时迫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡谓晌,死狀恐怖掠拳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情纸肉,我是刑警寧澤碳想,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站毁靶,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏逊移。R本人自食惡果不足惜预吆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望胳泉。 院中可真熱鬧拐叉,春花似錦、人聲如沸扇商。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽案铺。三九已至蔬芥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背笔诵。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工返吻, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人乎婿。 一個(gè)月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓测僵,卻偏偏與公主長得像,于是被迫代替她去往敵國和親谢翎。 傳聞我的和親對象是個(gè)殘疾皇子捍靠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容