關(guān)于離屏渲染

最近在學(xué)習(xí) UI 性能優(yōu)化方面的內(nèi)容,總結(jié)一下自己對(duì)離屏渲染的理解。很早就聽(tīng)過(guò)離屏渲染的概念,也查閱過(guò)資料,但一直沒(méi)有一個(gè)系統(tǒng)化的理解。這里通過(guò)幾個(gè)問(wèn)題,梳理了下自己對(duì)離屏渲染的理解。

1.什么是離屏渲染
2.如何觸發(fā)離屏渲染
3.離屏渲染的代價(jià)是什么
4.離屏渲染有沒(méi)有好處

1.什么是離屏渲染

離屏渲染(offscreen-rendering)顧名思義為屏幕外的渲染,即渲染的結(jié)果不會(huì)直接呈現(xiàn)到當(dāng)前屏幕上,而是等待合適的時(shí)機(jī)才會(huì)被顯示。

正常情況下,在當(dāng)前屏幕顯示的內(nèi)容,由 GPU 渲染完成后放到當(dāng)前屏幕的幀緩存區(qū),不需要額外的渲染空間。我們知道 iPhone 的屏幕刷新率是 60Hz,也就是刷新一幀的時(shí)間是 16.67 ms,每隔這段時(shí)間視頻控制器就會(huì)去讀一次緩存區(qū)的內(nèi)容來(lái)顯示。

假如 GPU 遇到性能瓶頸,導(dǎo)致無(wú)法在一幀內(nèi)更新渲染結(jié)果到幀緩存區(qū),那么從緩存區(qū)讀到的會(huì)是上一幀的內(nèi)容,導(dǎo)致幀率降低界面卡頓。

蘋果對(duì)于頁(yè)面流暢度的要求是非??量痰模绻?yè)面布局比較復(fù)雜,硬件遇到瓶頸,不能任由它卡頓。離屏渲染的機(jī)制就被引入,它會(huì)觸發(fā)比較消耗性能的視圖提前渲染。

2.如何觸發(fā)離屏渲染

有兩種觸發(fā)離屏渲染的方式,分別是被動(dòng)觸發(fā)和主動(dòng)觸發(fā)。

圓角,陰影,遮罩(mask),模糊,以及 iOS 9 之前圖片的圓角,圓角單純的設(shè)置 cornerRadius 并不會(huì)觸發(fā)離屏渲染,需要配合 masksToBounds 切割邊緣之外的子視圖。重寫-drawRect方法,視圖只要設(shè)置背景顏色,也會(huì)觸發(fā)離屏渲染。

主動(dòng)觸發(fā)離屏渲染的方式是利用 CALayer.shouldRasterize 屬性,開(kāi)啟光柵化。光柵化是一個(gè)比較抽象的概念,它的作用是強(qiáng)制將 CALayer 以 bitmap 的形式進(jìn)行緩存,等價(jià)于屏幕外的緩存,也屬于離屏渲染的概念。

被動(dòng)觸發(fā)離屏渲染的方式看起來(lái)毫無(wú)規(guī)律,但其實(shí)它們有一個(gè)共同的特征,就是含有透明度。含有透明度的視圖,在顯示前需要進(jìn)行圖層的合成,即對(duì)重疊視圖的每個(gè)像素的 R,G,B,A 值進(jìn)行重計(jì)算,最終顯示組合的效果。對(duì)于完全不透明的視圖,遮擋住父視圖的內(nèi)容,直接顯示最上層(葉節(jié)點(diǎn))的色值,就沒(méi)有組合的開(kāi)銷。

視圖的合成計(jì)算是非常消耗 GPU 性能,多層級(jí)大尺寸視圖尤為明顯。體現(xiàn)在代碼成面, GPU 是否進(jìn)行視圖的合成依據(jù)是 CALayer 的 opaque 屬性,如果為 YES 就不會(huì)進(jìn)行圖層的合成。然而,視圖透明度是由 alpha 屬性決定的,所以在修改 alpha 小于 1 時(shí),最好將 opaque 設(shè)為 NO,否則會(huì)出現(xiàn)無(wú)法預(yù)料的效果,這一點(diǎn)很容易被忽略。

3.離屏渲染的代價(jià)是什么

離屏渲染需要在屏幕外開(kāi)辟內(nèi)存空間,提前使用 CPU 渲染復(fù)雜的視圖,保證視頻控制器能夠及時(shí)地從緩存區(qū)讀到新的渲染結(jié)果。它在 GPU 面臨性能瓶頸時(shí),將壓力轉(zhuǎn)移一部分給比較空閑的 CPU,然而 CPU 的渲染能力遠(yuǎn)沒(méi)有 GPU 高效,有點(diǎn)殺雞出牛刀的意思。

同時(shí)這也是一種以空間換取時(shí)間的策略。

視頻控制器要讀取離屏渲染的結(jié)果,需要把渲染上下文從當(dāng)前屏幕緩存區(qū)切到屏幕外緩存區(qū),當(dāng)要顯示非離屏渲染視圖的時(shí)候又要切換回來(lái),然而不可能在一屏上所有的元素都是離屏渲染的,所以視頻控制器上下文需要不停地來(lái)回切換。而這種上下文切換的代價(jià)非常昂貴。

所以離屏渲染會(huì)帶來(lái)各方面的開(kāi)銷,要盡可能的避免。

4.離屏渲染有沒(méi)有好處

離屏渲染并不是一無(wú)是處的,雖然會(huì)造成很多額外的開(kāi)銷,但也是為了充分利用設(shè)備的資源來(lái)保證界面的流暢。發(fā)生離屏渲染時(shí),是為了引起開(kāi)發(fā)者對(duì)性能的關(guān)注,減少不必要的透明視圖層級(jí)。如果不可避免的要觸發(fā)離屏渲染,并且發(fā)生離屏渲染視圖內(nèi)容不會(huì)頻繁的變化,可以利用 CALayer.shouldRasterize 開(kāi)啟光柵化,將離屏渲染的內(nèi)容以位圖的形式緩存,減少?gòu)?fù)雜視圖頻繁渲染的開(kāi)銷。然而,這個(gè)緩存的時(shí)效是 100ms,也就是刷新 6 幀的時(shí)間,如果視圖內(nèi)容更新頻繁,緩存就會(huì)不停的刷新,導(dǎo)致無(wú)法命中,開(kāi)啟光柵化并沒(méi)有什么作用。

參考

1.理解什么是離屏渲染
http://www.10tiao.com/html/585/201803/2654061295/1.html
2.離屏渲染詳解
http://www.itdecent.cn/p/57e2ec17585b

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 屏幕顯示圖像的原理: 高中物理應(yīng)該學(xué)過(guò)顯示器是如何顯示圖像的:需要顯示的圖像經(jīng)過(guò)CRT電子槍以極快的速度一行一行的...
    青火閱讀 27,858評(píng)論 18 104
  • 相比于當(dāng)前屏幕渲染,離屏渲染的代價(jià)是很高的,這也是iOS移動(dòng)端優(yōu)化的必要部分。 OpenGL中,GPU屏幕渲染有以...
    一個(gè)人在路上走下去閱讀 9,108評(píng)論 0 74
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒(méi)有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,621評(píng)論 1 32
  • 前言 在最近的面試中,我發(fā)現(xiàn)一道面試題,其考點(diǎn)是:圍繞iOS App中一個(gè)視圖從添加到完全渲染,在這個(gè)過(guò)程中,iO...
    筑夢(mèng)師Winston閱讀 24,693評(píng)論 26 197
  • 圖像顯示原理 圖像顯示的大概流程: 程序運(yùn)行從內(nèi)存中讀取數(shù)據(jù)對(duì)圖片進(jìn)行解壓得到像素?cái)?shù)據(jù),若GPU不支持圖片的顏色格...
    foreverSun_122閱讀 718評(píng)論 0 2

友情鏈接更多精彩內(nèi)容