奇巴布Feed流性能優化

01

   項目背景


“愛奇藝奇巴布”是愛奇藝爲0-8歲孩子和家長定製化設計的寓教於樂平臺,爲兒童量身打造精緻的觀看體驗,精彩內容解鎖寓教於樂新方式。爲兒童提供優質動畫內容的同時,我們更關注APP用戶體驗。在產品交互設計上我們立足兒童視角,把內容瀏覽和觀影做到做到簡約易用。奇巴布APP整體界面簡約、導航清晰、播放流暢,以極致的設計理念榮獲2018年德國紅點傳達設計獎。

在技術側我們不斷完善技術架構體系,優化提升APP各項性能指標,發揮工匠精神把APP的用戶體驗做到極致。優化技術方向包括:APP冷啓動、Crash防控、內存管理、電量消耗、安裝包體積等。奇巴布APP歷經數年迭代開發,產品功能不斷完善,疊加兒童移動設備換新頻次相對成人低,奇巴布APP首頁Feed流在老舊設備滑動使用過程中會出現卡頓情況,滑動中有視頻播放等場景時頁面卡頓比較明顯,影響用戶體驗。


02

   問題現狀


  • 卡頓原因

屏幕刷新率由硬件決定,通常是 60Hz/S,或者由 OS 和硬件協調動態調整刷新率。當程序通過 CPU、GPU 渲染畫面的過程中,耗時超過一次刷新間隔,就會使得屏幕畫面沒有更新,導致卡頓現象產生,影響用戶體驗。

  • Feed卡頓問題分析

使用性能較差的手機滑動Feed流,通過Xcode-Instruments工具分析在滑動過程中具體耗時分佈情況。截取代表性性能分析圖,如下:

Hitch 出現時的耗時調用堆棧
滑動列表時的統計曝光耗時堆棧
Feed卡頓問題分析總結如下:
  1. Feed中存在較多不同樣式Card,多種Card類的合計初始化耗時較長;
  2. Feed中有各種圖片,這些本地圖片資源在主線程讀取和渲染,有性能提升空間;
  3. Feed滑動中圖片庫(基於SDWebImage二次開發)在讀取磁盤緩存文件過程中耗時較長,且在主線程中做讀取操作;
  4. Feed滑動過程中播放器開播與停播耗時較長;
  5. Feed滑動過程中Card區塊曝光引發頻繁Pingback投遞,整體耗時較長。

03

   解決方案


  • Card數據解析與渲染異步處理

使用QoS的NSQualityOfServiceUserInitiated創建自定義隊列,當前設備CPU活躍核心數和自定義最大核心數比較,獲得結果設置隊列上限。通過限制併發數量減少多個線程頻繁切換帶來CPU資源損耗,避免GCD API頻繁創建線程。Card數據解析和佈局計算、播放器內核初始化、圖片和文本渲染都使用該自定義隊列來處理。

  • 首頁Card預加載

在奇巴布Feed列表中前幾屏幕業務數據大多爲固定推薦內容組合,Card類型繁多無法複用,因此預先加載前幾屏不同Card實例是提高性能的一種技術手段。具體解決方案如下:

  1. 預加載策略:

    APP每次冷啓動時,總體策略是以最快速度展示內容給用戶,縮短啓動時間。首頁Feed接口在發送網絡請求過程中有網絡延遲,在服務端數據傳送到本地之前加載本地磁盤緩存的上次啓動時Feed流JSON數據。利用磁盤中持久化的JSON數據,解析出JSON對應的Card類,將常用的Card類名緩存到內存,以備在合適的時機初始化Card實例,以備後續滑動Feed時直接讀取Card實例,從而避免在滑動過程中初始化。

  2. 預加載時機的判別與執行:

在用戶啓動APP的瞬間,會存在大量異步業務操作搶佔CPU資源。所以需要尋找CPU閒置且用戶沒有手勢操作時預加載Card。監測與執行大體實現邏輯是:通過向主線程RunLoop添加Observer監聽DefaultMode,監聽作用的時間點爲線程進入休眠之前或RunLoop即將退出。當方法回調觸發時,意味着用戶沒有滑動或者滑動結束,在回調方法中做預加載。

  • 本地圖片預解碼

Feed中各種本地圖片

Feed中不同類型Card中的角標和佔位圖,這些圖片爲本地資源,在用戶滑動Feed時,過往實現方式是在主線程中從磁盤讀取資源,然後進行渲染。將這些I/O操作放入子線程,在圖標使用前提前生成Bitmap到內存中,可以減少用戶在滑動過程中因加載圖片帶來的性能損耗。具體解決方案如下:
  1. 預加載策略:
    在APP首頁渲染完成後,異步執行統計常用Card中依賴的角標和佔位圖,提前生成Bitmap, 並加載到內存。Hook圖片調用方法[UIImage imageNamed:],在後續調用[UIImage imageNamed:] 方法時將省去I/O和解碼過程,並通過以圖片名鍵值匹配方式存儲避免多次緩存。
  2. 解碼方案:
強制解碼過程:iOS15.0以上系統直接調用系統方法imageByPreparingForDisplay進行預解碼,其他系統版本則使用 CGBitmapContext 強制解碼。
  • 圖片庫讀取優化
圖片庫設置組件的圖片策略是通過異步下載URL對應圖片並做緩存。本次優化主要是針對已經加載到緩存的圖片,當對應Card再次滑入屏幕時,第一時間加載緩存中圖片而不是再走圖片庫內部方法各種業務邏輯判斷。
  • 其他優化
  1. 針對問題現狀中第4個問題:Feed滑動過程中播放器開播與停播耗時較長,解決辦法是在滑動時避免播放器的初始化,避免播放器的停播,維持播放狀態與滑動前一致。另外在Card停播時顯性的調用停止加載數據API,防止播放器在後臺異步加載數據。
  2. 針對問題現狀中第5個問題:Card區塊曝光引發頻繁Pingback投遞耗時較長,且在主線程中操作。解決思路是滑動時對統計方法限流、降低調用頻次。曝光精度會有非常小的下降,但在可接受範圍內。

04

   項目總結


  • 技術總結

以UML時序圖彙總優化技術點,如下圖:

  • 項目收益

使用Apple Xcode工具Scroll Hitch Rate監測優化效果,優化後每秒滑動掛起降低至1.4ms,遠低於Apple對滑動流暢的標準5ms/s,即使在性能較差的低端機上滑動也非常流暢,用戶體驗有較大提升。

注:Scroll Hitch Rate表示圖像幀延遲顯示在屏幕上的時間總和 Hitch time除以用戶滑動屏幕的持續時間 Scroll duration 得到一個比例,它可以反映用戶感受到的滑動卡頓的嚴重程度。

也許你還想看

Prometheus監控指標查詢性能調優

愛奇藝DRM修煉之路

組件化設計在會員業務的應用和實踐



本文分享自微信公衆號 - 愛奇藝技術產品團隊(iQIYI-TP)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章