本文是在前人總結(jié)的基礎(chǔ)上進(jìn)行高度概括贮庞,簡單介紹造成界面卡頓的原因和解決思路峦筒。
屏幕成像原理
首先從過去的 CRT 顯示器原理說起。CRT 的電子槍按照上面方式窗慎,從上到下一行行掃描物喷,掃描完成后顯示器就呈現(xiàn)一幀畫面,隨后電子槍回到初始位置繼續(xù)下一次掃描遮斥。為了把顯示器的顯示過程和系統(tǒng)的視頻控制器進(jìn)行同步脯丝,顯示器(或者其他硬件)會用硬件時鐘產(chǎn)生一系列的定時信號。當(dāng)電子槍換到新的一行伏伐,準(zhǔn)備進(jìn)行掃描時宠进,顯示器會發(fā)出一個水平同步信號(horizonal synchronization),簡稱 HSync藐翎;而當(dāng)一幀畫面繪制完成后材蹬,電子槍回復(fù)到原位,準(zhǔn)備畫下一幀前吝镣,顯示器會發(fā)出一個垂直同步信號(vertical synchronization)堤器,簡稱 VSync。顯示器通常以固定頻率進(jìn)行刷新末贾,這個刷新率就是 VSync 信號產(chǎn)生的頻率闸溃。盡管現(xiàn)在的設(shè)備大都是液晶顯示屏了,但原理仍然沒有變拱撵。
通常來說辉川,計算機(jī)系統(tǒng)中 CPU、GPU拴测、顯示器是以上面這種方式協(xié)同工作的乓旗。CPU 計算好顯示內(nèi)容提交到 GPU,GPU 渲染完成后將渲染結(jié)果放入幀緩沖區(qū)集索,隨后視頻控制器會按照 VSync 信號逐行讀取幀緩沖區(qū)的數(shù)據(jù)屿愚,經(jīng)過可能的數(shù)模轉(zhuǎn)換傳遞給顯示器顯示汇跨。
在最簡單的情況下,幀緩沖區(qū)只有一個妆距,這時幀緩沖區(qū)的讀取和刷新都都會有比較大的效率問題穷遂。為了解決效率問題,顯示系統(tǒng)通常會引入兩個緩沖區(qū)娱据,即雙緩沖機(jī)制蚪黑。在這種情況下,GPU 會預(yù)先渲染好一幀放入一個緩沖區(qū)內(nèi)吸耿,讓視頻控制器讀取祠锣,當(dāng)下一幀渲染好后,GPU 會直接把視頻控制器的指針指向第二個緩沖器咽安。如此一來效率會有很大的提升伴网。
雙緩沖雖然能解決效率問題,但會引入一個新的問題妆棒。當(dāng)視頻控制器還未讀取完成時澡腾,即屏幕內(nèi)容剛顯示一半時,GPU 將新的一幀內(nèi)容提交到幀緩沖區(qū)并把兩個緩沖區(qū)進(jìn)行交換后糕珊,視頻控制器就會把新的一幀數(shù)據(jù)的下半段顯示到屏幕上动分,造成畫面撕裂現(xiàn)象,如下圖:
為了解決這個問題红选,GPU 通常有一個機(jī)制叫做垂直同步(簡寫也是 V-Sync)澜公,當(dāng)開啟垂直同步后,GPU 會等待顯示器的 VSync 信號發(fā)出后喇肋,才進(jìn)行新的一幀渲染和緩沖區(qū)更新坟乾。這樣能解決畫面撕裂現(xiàn)象,也增加了畫面流暢度蝶防,但需要消費(fèi)更多的計算資源甚侣,也會帶來部分延遲。
那么目前主流的移動設(shè)備是什么情況呢间学?從網(wǎng)上查到的資料可以知道殷费,iOS 設(shè)備會始終使用雙緩存,并開啟垂直同步低葫。而安卓設(shè)備直到 4.1 版本详羡,Google 才開始引入這種機(jī)制,目前安卓系統(tǒng)是三緩存+垂直同步氮采。
卡頓產(chǎn)生的原因和解決方案
在 VSync 信號到來后,系統(tǒng)圖形服務(wù)會通過 CADisplayLink 等機(jī)制通知 App鹊漠,App 主線程開始在 CPU 中計算顯示內(nèi)容主到,比如視圖的創(chuàng)建躯概、布局計算登钥、圖片解碼娶靡、文本繪制等牧牢。隨后 CPU 會將計算好的內(nèi)容提交到 GPU 去,由 GPU 進(jìn)行變換姿锭、合成塔鳍、渲染呻此。隨后 GPU 會把渲染結(jié)果提交到幀緩沖區(qū)去轮纫,等待下一次 VSync 信號到來時顯示到屏幕上焚鲜。由于垂直同步的機(jī)制掌唾,如果在一個 VSync 時間內(nèi),CPU 或者 GPU 沒有完成內(nèi)容提交忿磅,則那一幀就會被丟棄糯彬,等待下一次機(jī)會再顯示,而這時顯示屏?xí)A糁暗膬?nèi)容不變葱她。這就是界面卡頓的原因。
從上面的圖中可以看到吨些,CPU 和 GPU 不論哪個阻礙了顯示流程,都會造成掉幀現(xiàn)象锤灿。所以開發(fā)時,也需要分別對 CPU 和 GPU 壓力進(jìn)行評估和優(yōu)化但校。
綜上所述,實(shí)際項目中状囱,一般可以將布局信息提前計算好并緩存,滑動tableview的時候盡量減少cpu計算布局信息的使用亭枷。
更多優(yōu)化方法請移步
iOS 保持界面流暢的技巧