《iOS之一起進(jìn)大廠》系列-iOS如何監(jiān)控界面卡頓掉幀,如何優(yōu)化

學(xué)而時(shí)習(xí)之,不亦說(shuō)乎

PS: 下面用模仿面試的問(wèn)答模式,把相關(guān)的問(wèn)題和知識(shí)點(diǎn)串聯(lián)起來(lái)。 這樣可以提高閱讀體驗(yàn),還可以加深記憶。

開(kāi)始面試

我正在會(huì)議室等待,忽然看到一個(gè)穿著格子襯衫,大腹便便的中年男子拿著簡(jiǎn)歷向我走來(lái), 我看著他頭上快要絕頂?shù)念^發(fā),心想這肯定是個(gè)iOS開(kāi)發(fā)技術(shù)牛逼閃閃的老前輩。 還好看過(guò)《iOS之一起進(jìn)大廠》系列,想想現(xiàn)在是滿腹經(jīng)綸,剛緊張到提到嗓子眼的心,又按下去了,淡定從容,一點(diǎn)都不虛好伐,就是這么自信淡定。

小伙子,看你簡(jiǎn)歷上提到,對(duì)視圖的性能優(yōu)化有一些了解,你可不可以先說(shuō)下 圖像顯示相關(guān)的原理

帥氣逼人的面試官您好, iOS系統(tǒng)中 CPU、GPU、顯示器是以下面圖中方式協(xié)同工作的。CPU和GPU是通過(guò)總線鏈接起來(lái)的,CPU 計(jì)算好顯示內(nèi)容提交到 GPU,GPU 渲染完成后將渲染結(jié)果放入幀緩沖區(qū),視頻控制器會(huì)按照 VSync 信號(hào)逐行讀取幀緩沖區(qū)的數(shù)據(jù),經(jīng)過(guò)數(shù)模轉(zhuǎn)換傳遞給顯示器顯示。 下圖就是圖像顯示的流程:

關(guān)于CPU和GPU的分工又有以下內(nèi)容:

  • CPU負(fù)責(zé):

    • 對(duì)象創(chuàng)建和銷毀
    • 對(duì)象屬性調(diào)整
    • 布局計(jì)算、文本的計(jì)算
    • 排版、圖片的格式轉(zhuǎn)換和解碼
    • 圖像的繪制
  • GPU負(fù)責(zé):

    • 紋理的渲染
    • 視圖的混合
    • 圖形的生成

既然了解圖像顯示的原理,那你知道IOS視圖卡頓掉幀的原因嗎?

標(biāo)準(zhǔn)情況下,頁(yè)面滑動(dòng)流暢是60FPs ,就是每一秒有60幀的畫(huà)面刷新,每16.7ms(1/60秒)有一幀數(shù)據(jù)。上圖兩個(gè)VSync 之間的時(shí)間就是16.7ms。 如果CPU 和 GPU 加起來(lái)的處理時(shí)間超過(guò)了 16.7ms,就會(huì)造成掉幀甚至卡頓。當(dāng)FPs 幀數(shù)低于30時(shí),人的肉眼就能感覺(jué)到畫(huà)面明顯的卡頓。

面試官吹了下自己的頭發(fā)簾,心想,小伙子不錯(cuò),都回答到點(diǎn)子上了,那再聊的深一點(diǎn),那你知道如何監(jiān)控界面的卡頓嗎

既然知道了造成卡頓的原因,監(jiān)控卡頓的思路就有了。

  • 思路一:監(jiān)控一秒鐘內(nèi)的幀數(shù)是否經(jīng)常低于或遠(yuǎn)低于 60FPs。
  • 思路二:監(jiān)控每一幀的時(shí)長(zhǎng)是否超時(shí)。

思路一實(shí)現(xiàn)方法:用 CADisplayLinker 來(lái)計(jì)數(shù)

CADisplayLink可以以屏幕刷新的頻率調(diào)用指定selector,iOS系統(tǒng)中正常的屏幕刷新率為60次/秒,只要在這個(gè)方法里面統(tǒng)計(jì)每秒這個(gè)方法執(zhí)行的次數(shù),通過(guò)次數(shù)/時(shí)間就可以得出當(dāng)前屏幕的刷新率了。

思路二實(shí)現(xiàn)方法:通過(guò)子線程監(jiān)測(cè)主線程的RunLoop,判斷兩個(gè)狀態(tài)RunLoop的狀態(tài)區(qū)域之間的耗時(shí)是否達(dá)到一定閾值。

開(kāi)啟子線程,實(shí)時(shí)計(jì)算這兩個(gè)狀態(tài)區(qū)域之間的耗時(shí)是否到達(dá)某個(gè)閥值,便能揪出這些性能殺手,假定連續(xù)6次超時(shí)50ms認(rèn)為卡頓(當(dāng)然也包含了單次超時(shí)300ms)

老面試官露出了滿意的笑容,不過(guò)做戲做要做全套嘛,那你最后說(shuō)說(shuō)如何優(yōu)化掉幀卡頓

圖像顯示的工作是由CPU和GPU協(xié)同完成的, 那么優(yōu)化的方向和思路就是盡量減少他們的處理時(shí)長(zhǎng)。

對(duì)CPU處理的優(yōu)化:

  • 在子線程中進(jìn)行對(duì)象的創(chuàng)建,調(diào)整和銷毀,節(jié)省一部分CPU的時(shí)間
  • 在子線程中預(yù)排版(布局計(jì)算,文本計(jì)算),讓主線程有更多的時(shí)間去響應(yīng)用戶的交互
  • 對(duì)文本等異步繪制,圖片編解碼等內(nèi)容進(jìn)行 預(yù)渲染、預(yù)排版

對(duì)GPU處理的優(yōu)化

  • 盡量避免使用 CALayer 的 Border、corner、shadow、mask 等技術(shù),這樣能少觸發(fā)離屏渲染
  • 盡可能將多張圖片合成為一張進(jìn)行顯示,減輕視圖層級(jí)

面試結(jié)束

小伙子回答的不錯(cuò),明天接著面試其他內(nèi)容。 天吶嚕,明天還有。

總結(jié)

文中主要是針對(duì)了圖像原理,卡頓掉幀的原因,優(yōu)化方案。

  • 原理:CPU負(fù)責(zé)計(jì)算,GPU負(fù)責(zé)渲染,渲染結(jié)果放到幀緩沖區(qū)再到顯示器上顯示。
  • 原因:CPU加GPU的處理耗時(shí)超過(guò)1/60秒時(shí),就出現(xiàn)了掉幀,甚至卡頓。
  • 監(jiān)控:監(jiān)控掉幀卡頓有兩種思路,監(jiān)控 時(shí)間內(nèi)幀數(shù) 和RunLoop兩狀態(tài)間的耗時(shí)是否超過(guò)閾值。

其實(shí)對(duì)視圖的優(yōu)化還有很多方面,比如使用UIView的異步繪制,如何避免離屏渲染,在使用TableView 如何具體優(yōu)化沒(méi)有提到,這些需要另外的文章篇幅才能描述清楚。 不用全堆到一起。

堅(jiān)持看到這里的同學(xué),你們個(gè)個(gè)都是人才,我好喜歡。

作者:空杯子
鏈接:https://juejin.im/post/5efc52495188252e6c60d829

最后編輯于
?著作權(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ù)。

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