一、背景
提到性能優化,跟頁面相關的就兩個指標:冷啓動時長和頁面 FPS 冷啓動時長用來表徵用戶在首次打開頁面時到頁面渲染完成的耗時,很明顯這個耗時越短,用戶的體驗將會越好。而 FPS 則表示頁面渲染的幀率,FPS 越高,表示頁面交互越流暢。所以我們的目標是:冷啓動時長得低,FPS 得高,這樣就表示用戶能快速進入頁面並且愉快的交互了。
隨着業務複雜度的增加,發現頁線上的冷啓動耗時有點差強人意,於是就有了這一波發現頁的冷啓動優化。
二、思路
基於以前優化經驗,迅速整理出了優化思路,並形成如下腦圖:
三、優化結果
1)低端機自然冷啓到頁面渲染完畢進 1s,目前實驗室數據 892ms,行業對比數據如下:
2)低端機 push 冷啓到視頻起播進 5s,優化前後對比效果如下:
四、主路徑梳理
針對發現頁,對其啓動主路徑梳理如下:
五、懶加載
依賴阿里中間件 AppMonitor 的頁面完成的回調接口,通過將所有可以懶加載的任務用 MonitorTask 包裝後拋給 PageMonitorTaskDomain 在合適的時機執行,如:當 page 處在可交互的狀態時執行:
@Override
public void onPageChanged(final String name, final int state, final long l) {
if (state = INTERACTIVE) {
doDelayedTask();
}
}
幾個主要的懶加載項:
1)Tab 動畫;
2)Poplayer;
3)卡片推薦任務;
4)Viewpager 左右 Tab 懶加載;
5)各種業務(換膚、福利球等)。
六、預加載
創建預加載池,會在 Application OnCreate 中啓動異步線程,加載需要被預加載的資源。
1)預創建 Tabview,預加載 Tab 數據,預解析 Tab 數據;
2)預加載類;
3)預加載關注 SDK;
4)預加載主 Fragment;
5)預加載 Delegate;
6)預加載以及預處理緩存以及快照。
七、其他優化
1)直接創建 Delegate,而非通過配置文件配置再反射創建; 2)整合 Delegate,減少向 EventBus 的註冊次數; 3)減少字符串拼接操作。
八、快照
由於緩存數據處理是異步的,低端機進入發現後,等待緩存數據處理完成總得有個 Loading 界面,即使提前預加載緩存數據以及預處理好,低端機也不能避免 Loading,爲了讓用戶不再看到過渡頁面或者菊花,就得保證主線程能夠帶着數據渲染,而不是等數據好了後再更新界面。可惜的是,即使緩存反序列後,通過一頓猛如虎的操作:創建 Model、創建 Adapter、卡片佈局優化,還是需要 200ms 的時間渲染 3 張卡片。最後,只能通過加載輕量級的緩存數據——快照來完成首屏的展示,加載緩存數據攏共分三步:
1)緩存數據的時候保存一份快照,只保留最簡單的一些屬性(低質量封圖鏈接,PGC 信息);
2)預加載快照,預創建用於展示快照的容器 view(inflate 或者直接代碼實現都可以);
3)進入發現後,優先展示快照,得緩存數據渲染完後,移出快照。
優化後的效果如下:
九、Push 冷啓
藉助自然冷啓的優化成果以及 push 鏈路的特殊性——以視頻起播爲目標,特地針對 push
冷啓做了以下優化:
1)預加載視頻資源;
2)預初始化播放器;
3)去掉 Push 鏈路不需要的異步任務(緩存以及快照相關的邏輯);
4)調整 Push 鏈路,以視頻起播爲最高優先級,改造後的鏈路如下:
十、總結
啓動優化主旨就一個:主線程只做 UI 操作。相伴的手段就是異步預加載,同步懶加載。另外也需要具體場景具體分析,大體步驟就是:通過工具導出啓動 Trace 日誌,分析整個啓動路徑的耗時因素,優先解決明顯的耗時問題,後續再各個擊破。一般情況下,在優化到可接受的目標後即可,而不需要優化到極致,因爲性能的優化往往會帶來額外的複雜度,比如以上提到的 Push 場景和正常的啓動場景就不能複用相同的邏輯。
優化達到目標後需要守護住成果,在日常開發時需要嚴格守住 UI 線程的底線,上線後需要時常關注性能數據,這樣攻防堅守才能持續交付高性能的成果。
作者 | 阿里文娛高級開發工程師 紙貴