天天看點

iOS 性能檢測新方式​——AnimationHitches

作者| 岚遙

iOS 性能檢測新方式​——AnimationHitches

AnimationHitches 的運作原理

背景

在 Xcode12 中,Instrument 新增 AnimationHitches 檢測類型用以檢測卡頓,并去除 CoreAnimation 檢測方式。在支援 PromotionDisplay 的裝置上幀率可調整至 120 幀,并且會根據目前使用者手勢和裝置狀态進行動态調整。此時再繼續使用幀率來判斷性能的好壞及流暢度将會是一個錯誤的選擇。是以 AnimationHitches 主要用于代替幀率檢測,并且提出 卡頓時間比(Hitch Time Ratio) 的概念用于替代 FPS。由于目前關于 Hitch 相關的資料很少,而在 iPhone13Pro 之前 iPhone 螢幕最高重新整理頻率仍為 60 HZ,是以很多同學都還未關注到該能力。是以本篇将主要介紹 Hitch(卡頓) 的概念、RenderLoop(渲染循環) 的整體流程,卡頓類型及如何避免卡頓。

什麼是卡頓?

▐  概念

任何時候螢幕上出現晚于預計的幀都屬于卡頓。

iOS 性能檢測新方式​——AnimationHitches

▐  執行個體

例如 滾動動畫(Scroll)、點選動畫(Animation)、轉場動畫(Transition),這些流暢的動畫建構了一種使用者和螢幕内容的視覺連接配接感,而如果動畫卡頓會導緻動畫畫面跳躍,打破這種連接配接感,使用者體驗會變得很差。

iOS 性能檢測新方式​——AnimationHitches

布局階段

在布局階段, layoutSubviews 會被所有需要布局的 View 調用。比如布局視圖(frame、bounds、transform),增加或移除視圖,亦或是直接調用 setNeedsLayout。注意這些布局操作并非立即執行,系統會合并這些布局請求,在 Runloop 休眠前統一執行這些操作。

顯示階段

在顯示階段,drawRect 會被每個需要被更新的 View 調用。比如 UILabel、UIImageView 或者隻是任何重寫 drawRect 方法的類。他們必須調用 setNeedsDisplay 用以支援 View 的更新。在繪制時每個自定義的繪圖圖層都會接收到帶紋理的 CoreGraphics 的背景。他們将利用 CoreAnimation 進行繪制,這些圖層就變成了圖檔。是以如果沒有必要則不要重寫 drawRect 方法,其不僅會額外開辟一塊記憶體用以存儲 bitmap,還會在 CPU 上進行繪制,增加了整體主線程時間占用,當自定義 drawRect 視圖較多時,對整體的記憶體壓力也比較大。

iOS 性能檢測新方式​——AnimationHitches
準備階段

在 Prepare 階段還沒有解碼的圖像将會在這一步進行解碼,也就是我們需要優化的常見的圖檔主線程解碼操作。

對于每個被解碼的圖像, App 可能會持續存在大量的記憶體配置設定。這種記憶體配置設定與輸入圖像的大小成正比,而與 FrameBuffer 中實際渲染的圖像視圖的大小沒有必然聯系。當 App 占用越來越多的記憶體時,作業系統将會開始壓縮實體記憶體(physical memory)。整個過程都需要 CPU 的參與,是以除了我們自己的 App 對 CPU 的使用外,還可能會增加無法控制的全局 CPU 使用率。最終,我們的 App 可能會消耗更多的實體記憶體,以至于作業系統需要啟動終止程序,它将從低優先級的背景程序開始。如果我們的 App 對記憶體的消耗了達到了特定數量,可能會被終止,這也就是為什麼經常會因為大圖的原因産生 OOM。

若某個圖像的顔色格式 GPU 無法直接使用,也會在這一步進行格式轉換。這就要求對該圖像進行 copy 操作,而不是直接使用指針,這樣會耗時更長及占用更多的記憶體。

送出階段

在送出階段中,視圖樹将會被遞歸打包并發送到 RenderServer 中,是以當視圖層級較為複雜時,這個過程耗費的時間也會更長一些,是以需要盡量減輕視圖層級結構。

  • RenderServer

RenderServer 負責将我們的圖層樹轉換為真正可顯示的圖像。RenderServer 有兩個階段:Prepare 和 Execute 。在 Prepare 階段我們的圖層樹被編譯成一系列簡單的指令,供 GPU 執行,幀動畫也在此處進行處理。在渲染執行階段 GPU 将 App 的圖層繪制成最終圖像。

總結

本篇主要讨論了 RenderLoop 以及新的一幀展現給使用者的整個流程,并且着眼于什麼是卡頓,以及它的兩種類型:送出卡頓以及渲染卡頓。并最終定義了卡頓時間比用以測量目前 App 的卡頓程度和性能。相信大家對整個渲染循環和卡頓類型有了更清晰的認識,在日常編碼中也可以盡量避免這些問題。

本篇主要介紹了一些原理相關的概念,那麼具體的卡頓應該如何測量?下一篇将會通過實踐結合 Instrument 的 AnimationHitches 能力分析 DXSDK 作為卡片層面在日常資訊流的使用過程中在性能方面存在的一些問題,以及 DXSDK 上半年做的一些性能優化改進。