<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          iOS性能優(yōu)化——離屏渲染的分析探究

          共 3882字,需瀏覽 8分鐘

           ·

          2022-04-24 02:07

          前言


          性能優(yōu)化是我們開發(fā)中經(jīng)常提到的話題,而離屏渲染是我們在性能優(yōu)化過程中要關(guān)注的一部分??赡芪覀冊谔幚磉^程中都了解了優(yōu)化方法,但是離屏渲染背后的實(shí)現(xiàn)的原理是怎么樣的呢?今天這篇文章就帶大家了解一下離屏渲染,在說離屏渲染之前請大家先思考以下幾個(gè)問題:

          1、 什么是離屏渲染?

          2、 離屏渲染為什么會有性能損耗?

          3、 常見的離屏渲染場景有哪些?

          4、 怎么避免離屏渲染?

          在此之前我們需要先了解幾個(gè)概念。


          01
          CPU&GPU



          我們都知道可視化程序是由CPU和GPU協(xié)作完成的,首先我們先了解一下這兩個(gè)概念:

          CPU(Central Processing unit):中央處理器,作為計(jì)算機(jī)系統(tǒng)的控制和運(yùn)算核心,是信息處理、程序運(yùn)行的最終執(zhí)行單元。

          GPU(Graphics Processing unit):圖形處理器,一種可進(jìn)行繪圖運(yùn)算工作的專用微處理器,具有非常強(qiáng)的并行計(jì)算能力。

          CPU擅長分支預(yù)測等復(fù)雜操作,是一個(gè)復(fù)雜勞動過程;GPU擅長對大量數(shù)據(jù)進(jìn)行簡單操作,是一個(gè)大量并行工作的過程,GPU可以看做是一種專用的CPU,為單指令在大量數(shù)據(jù)上工作而設(shè)計(jì),這些數(shù)據(jù)內(nèi)容都是相同的操作。


          02
          屏幕顯示圖像原理



          在介紹屏幕圖像顯示的原理之前,我們需要先從 CRT 顯示器原理說起,如下圖所示,CRT 的電子槍從上到下逐行掃描,掃描完成后顯示器就呈現(xiàn)一幀畫面。然后電子槍回到初始位置進(jìn)行下一次掃描。為了同步顯示器的顯示過程和系統(tǒng)的視頻控制器,顯示器會用硬件時(shí)鐘產(chǎn)生一系列的定時(shí)信號。當(dāng)電子槍換行進(jìn)行掃描時(shí),顯示器會發(fā)出一個(gè)水平同步信號(horizonal synchronization),簡稱 HSync;而當(dāng)一幀畫面繪制完成后,電子槍回復(fù)到原位,準(zhǔn)備畫下一幀前,顯示器會發(fā)出一個(gè)垂直同步信號(vertical synchronization),簡稱 VSync。顯示器通常以固定頻率進(jìn)行刷新,這個(gè)刷新率就是 VSync 信號產(chǎn)生的頻率。

          一般來說,CPU計(jì)算好顯示內(nèi)容提交至GPU,GPU渲染完成后將渲染結(jié)果存入幀緩沖區(qū),視頻控制器會按照VSync信號逐幀讀取幀緩沖區(qū)的數(shù)據(jù),經(jīng)過數(shù)據(jù)轉(zhuǎn)換后最終由顯示器進(jìn)行顯示. 下圖所示為常見的CPU、GPU顯示器工作方式:


          ? ??

          03
          渲染顯示流程



          APP本身并不負(fù)責(zé)渲染,渲染則是由一個(gè)獨(dú)立的進(jìn)程(Render Server)負(fù)責(zé),APP通過進(jìn)程間通信將渲染任務(wù)及相關(guān)數(shù)據(jù)提交給Render Server。Render Server處理完數(shù)據(jù)后,再傳遞給GPU,最終GPU調(diào)用iOS的圖像設(shè)備進(jìn)行顯示。渲染顯示流程可以概括為:

          • CoreAnimation提交會話,包括自己和子樹的layout狀態(tài)等

          • Render Server解析提交的子樹狀態(tài),生成繪制指令

          • GPU執(zhí)行繪制指令

          • 顯示渲染后的數(shù)據(jù)

          CoreAnimation提交可細(xì)分為4個(gè)階段:布局(Layout)、顯示(Display)、準(zhǔn)備提交(Prepare)、提交(Commit)

          其具體的流程圖如下:


          ? ??

          什么是離屏渲染


          接下來我們來了解一下什么是離屏渲染。

          屏幕渲染有兩種方式:當(dāng)前屏幕渲染和離屏渲染。

          當(dāng)前屏幕渲染:在當(dāng)前用于顯示的屏幕緩沖區(qū)(frame buffer)中進(jìn)行渲染。

          離屏渲染:GPU或CPU在當(dāng)前屏幕緩沖區(qū)外新開辟一個(gè)緩沖區(qū)進(jìn)行渲染。

          其簡單示例圖如下:


          ? ??

          離屏渲染的性能損耗


          離屏渲染在當(dāng)前屏幕緩沖區(qū)外另開辟了一個(gè)緩沖區(qū)進(jìn)行渲染操作,造成其性能損耗的主要原因是因?yàn)閯?chuàng)建離屏渲染區(qū)和上下文的切換,其中上下文切換主要是當(dāng)發(fā)生離屏渲染時(shí)視頻控制器要去讀取緩存中的內(nèi)容,渲染上下文需要從當(dāng)前屏幕緩存區(qū)切換到屏幕外緩沖區(qū),當(dāng)非離屏渲染時(shí)候渲染上下文要切換到當(dāng)前屏幕緩沖區(qū)。當(dāng)一屏控件元素都發(fā)生離屏渲染時(shí),這種從當(dāng)前屏幕緩沖區(qū)切換至屏幕外緩存區(qū)會進(jìn)行多次,自然就會發(fā)生性能的損耗。


          離屏渲染何時(shí)發(fā)生及觸發(fā)場景


          從上文中我們可以了解離屏渲染產(chǎn)生的原因是因?yàn)殡x屏渲染在當(dāng)前屏幕外會創(chuàng)建一個(gè)離屏渲染區(qū)(offscreen frame buffer),在這個(gè)渲染區(qū)內(nèi)部是用來存放全局操作過程的渲染結(jié)果。layer的陰影、蒙版、模糊、光柵化、圓角等操作,因?yàn)檫@些操作會進(jìn)行多個(gè)渲染結(jié)果的合并,需要一個(gè)額外的渲染區(qū)來暫存渲染結(jié)果。因?yàn)橛|發(fā)離屏渲染本質(zhì)上是因?yàn)樯婕暗蕉鄠€(gè)渲染結(jié)果合并時(shí),需要借助離屏渲染區(qū)來暫存渲染結(jié)果。


          01
          圓角的設(shè)置



          單純的只設(shè)置cornerRadius和masksToBounds并不會觸發(fā)離屏渲染,我們需要看它要處理幾層渲染數(shù)據(jù)。下面我們通過代碼來查看,通過模擬器打開離屏渲染顏色標(biāo)記調(diào)試:


          ? ??

          從上圖中可以看到當(dāng)我們僅僅設(shè)置iamgeView的layer的cornerRadius和masksToBounds時(shí)候并不會觸發(fā)離屏渲染,如果我們這時(shí)候新增設(shè)置了imageView的背景色就會觸發(fā)離屏渲染,這是因?yàn)槲覀冊O(shè)置背景色及圖片進(jìn)行渲染時(shí)候,會先處理背景色將背景色處理完成放到offScreen buffer中,接著進(jìn)行圖片的處理操作,當(dāng)圖片處理完成后會放到offScreen buffer中,繼續(xù)進(jìn)行圓角的設(shè)置,等所有的操作處理完成后最終結(jié)果存儲進(jìn)行最終的展示。我們設(shè)置layer的邊框或者顏色同樣也會觸發(fā)離屏渲染,因?yàn)槲覀冊O(shè)置圖片的背景、layer層的邊框及顏色改變的是視圖層的內(nèi)容content,當(dāng)我們再設(shè)置了masksToBounds為Yes就會導(dǎo)致離屏渲染。

          同樣UIView設(shè)置添加子視圖進(jìn)行圓角設(shè)置時(shí)候也會觸發(fā)離屏渲染,其代碼圖示如下:


          ? ??

          圓角設(shè)置觸發(fā)離屏渲染不是設(shè)置了cornerRadius和masksToBounds就一定會觸發(fā)離屏渲染,單圖層的時(shí)候并不會觸發(fā)離屏渲染,只有處理多圖層時(shí)并且這時(shí)候masksToBunds設(shè)置為YES才會觸發(fā)。


          02
          蒙版



          官方給的蒙版渲染流程如下:

          • 渲染layer的mask紋理

          • 渲染layer的content紋理

          • 合并操作,合并mask和content紋理

          由于有兩層渲染結(jié)果,所以處理合并之前需要額外的緩存區(qū)來儲存處理結(jié)果,這時(shí)候也就會觸發(fā)離屏渲染了。我們可以用模擬器實(shí)驗(yàn)一下:


          ? ??

          同樣iOS8提供的UIVisualEffectView也會觸發(fā)離屏渲染,其導(dǎo)致離屏渲染的原理和蒙版觸發(fā)離屏渲染的原理類似,其渲染流程如下:

          • 渲染layer的內(nèi)容content

          • 捕獲內(nèi)容 (capture coneter)

          • 對內(nèi)容橫向模糊

          • 對內(nèi)容縱向模糊

          • 合成處理操作(Upscale and tint)

          通過其設(shè)置模糊效果需要更多的處理步驟來存儲渲染結(jié)果,會觸發(fā)離屏渲染,性能也隨之有影響的。

          組透明度allowsGroupOpacity、陰影(Shadow)僅僅只設(shè)置shadowoffset同樣也會觸發(fā)離屏渲染。原理同上都是因?yàn)閮H僅靠frameBuffer是不能實(shí)現(xiàn)最終效果的,只能另開辟離屏渲染區(qū)進(jìn)行渲染處理合成最終的結(jié)果進(jìn)行顯示。


          ? ??

          03
          光柵化



          光柵化開啟后,會觸發(fā)離屏渲染。當(dāng)CALayer的shouldRasterize設(shè)置為YES時(shí),可以將圖層繪制的結(jié)果緩存起來方便下次使用,但是光柵化開啟還是要根據(jù)我們使用場景來判斷,如果我們的圖像內(nèi)容不經(jīng)常進(jìn)行改變,我們可以開啟,因?yàn)閳D像內(nèi)容不變并且有復(fù)雜內(nèi)容的重繪的時(shí)候,開啟光柵化后,將渲染結(jié)果緩存后,下次使用時(shí)候可以直接讀取緩存,當(dāng)然這個(gè)緩存我們也不能過度使用的,這個(gè)緩存大小是限制在2.5倍的屏幕大小的,并且這個(gè)緩存結(jié)果超過100ms未使用的話,就會被丟棄的。光柵化的開啟導(dǎo)致的離屏渲染,大家有興趣的可以自己動手寫一下,這里就不做詳細(xì)介紹了。


          如何避免離屏渲染


          1、 圓角的處理

          我們開發(fā)中其實(shí)主要有對圖片圓角處理、滾動視圖各種Cell及其上面控件元素的圓角設(shè)置(部分特殊場景各個(gè)Section內(nèi)部上下圓角的單獨(dú)設(shè)置)這時(shí)候我們可以通過Core GraPhics框架處理或者配合貝塞爾曲線設(shè)置。



          我在這里只簡單介紹了兩種處理方式,處理圓角的方式不僅僅是上面的方法,只要我們在設(shè)置圓角的時(shí)候不過多觸發(fā)離屏渲染就可以,尤其是處理滾動視圖及其上元素控件需要圓角設(shè)置的時(shí)候。針對imageVIew視圖設(shè)置的時(shí)候,如果我們沒有其他特殊的設(shè)置,不設(shè)置backgroundColor,那么我們是可以直接設(shè)置cornerRadius的。

          2、 蒙版、視圖模糊、光柵化、陰影我們其實(shí)完全可以具體場景具體分析,layer層的蒙版使用layer.mask會觸發(fā)離屏渲染,一般蒙版使用場景是蒙版引導(dǎo)圖,圖層蒙版的效果替代我們完全可以使用添加自定義view來達(dá)到我們做到的效果,有一些特殊的使用場景,我們也可以配合CAShapeLayer進(jìn)行處理。而針對視圖模糊處理,我們可以避免使用系統(tǒng)提供的UIVisualEffectView,使用CoreImage提供的方法實(shí)現(xiàn)模糊效果或者Accelerate.Framework內(nèi)部的方法來實(shí)現(xiàn)。陰影的處理我們可以使用shadowPath來處理陰影效果,而光柵化如果內(nèi)容不變涉及到多圖層的復(fù)雜繪制效果我們可以開啟,減少性能的損耗。



          總結(jié)


          離屏渲染的處理僅僅是我們?nèi)粘KP(guān)注的性能優(yōu)化的其中一個(gè)點(diǎn),我們在業(yè)務(wù)場景處理中也要根據(jù)具體場景去分析,并不是所有的離屏渲染都是必須避免的,開辟額外的幀緩沖區(qū)雖然有一定的性能損耗,但是保存渲染結(jié)果并進(jìn)行最終的視圖顯示也是為了保證我們視圖的流暢性的。最后希望本文對離屏渲染的探究對大家后續(xù)開發(fā)及離屏渲染方面的性能優(yōu)化有所幫助。

          瀏覽 113
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  色天堂视频在线观看 | 一级日屄毛片免费播放 | 日本亚洲色大成网站www久久 | 日日夜夜精品视频免费 | 男人的天堂青青草视频 |