Android篇 | 愛奇藝App啟動最佳化實踐分享

愛奇藝技術產品團隊發表於2022-12-05

導讀
效能最佳化一直都是各個APP推進中的重點、難點,愛奇藝 App也不例外。在此之前,愛奇藝App Android 版的啟動速度雖然一直處於同類App領先的水平,但優勢距離其他同類的APP距離一直很小。面對這一瓶頸,愛奇藝技術產品團隊為愛奇藝App的啟動最佳化搭建了專項團隊。在各個團隊的大力支援下,將啟動時間由1.5s最佳化到了0.5s,實現了巨大跨越,下文將分享愛奇藝App啟動的最佳化實踐。

本文長度為2914字,預估閱讀時間8分鐘

凡事預則立,不預則廢

關於App 的啟動最佳化, 大部分的技術同學第一反應是延遲執行任務,再透過做一些程式碼實現上的最佳化來提高程式碼的執行效率。愛奇藝App 早期的最佳化策略也是如此:將某些啟動階段不必要執行的任務延遲到首頁某個生命週期之後再執行,或是延遲固定時間之後再執行等等。

這一最佳化策略在前期的確有一些效果,但是後來就收益甚微了。愛奇藝App(Android)經過多年的穩定迭代, 功能不斷豐富,程式碼量也越來越龐大。啟動階段涉及了很多業務的初始化功能,業務之間又有著複雜的依賴關係,輕易變更程式碼執行時序可能會導致崩潰或者某些業務異常。之前簡單的延遲最佳化策略已經很難再取得收益,一種全新的最佳化方案已經迫在眉睫。

工欲善其事,必先利其器

有沒有一種工具能直接看到當前任務執行的瓶頸呢?做過Android效能最佳化的同學應該都會比較熟悉Systrace和 TraceView這兩款工具。但是這還不夠,我們需要一款更為直觀、便捷的工具。它能夠把啟動階段程式碼執行的先後順序、時間間隔、執行緒情況以及程式碼位置等資訊直觀的展示出來,讓我們能一眼看出某一階段的任務排程是否合理,然後再根據實際情況進一步做有針對性的最佳化。

但到目前為止,我們尚未發現業內有滿足此需求的現成工具。然而在一年前,我們團隊自主開發了一款Lens開發除錯工具,它能夠以SDK的形式接入任意的Android 應用程式,可以提供任務分析、網路分析(抓包)、頁面分析(檢視拾取、檢視層級等)、沙盒訪問、快捷入口等等功能。於是我們團隊經過討論,決定用Lens來實現任務分析的功能,這樣既能完成啟動最佳化,又能進一步完善Lens的功能。經過我們團隊持續不斷的完善和最佳化,突破重重技術難關。終於實現了可以直接看見任務的執行狀況的能力,就像醫生拿到了病人的CT報告,精準最佳化已準備就緒。


Android篇 | 愛奇藝App啟動最佳化實踐分享

最佳化前啟動耗時與執行緒資訊(Debug)

Android篇 | 愛奇藝App啟動最佳化實踐分享

最佳化前啟動任務情況(Debug)

Android篇 | 愛奇藝App啟動最佳化實踐分享 

最佳化前啟動任務執行時序(Debug)

診斷:啟動階段有大量的執行緒啟動,執行了大量的任務,並且主執行緒任務十分密集。 

經過充分的思考後,我們團隊給出瞭如下的最佳化方案:

·   任務化:將啟動階段的程式碼按照業務邏輯封裝成獨立任務,方便管理和排程。

·   併發:將啟動階段的任務儘量併發執行。

·   延遲:啟動階段只執行第一個頁面渲染展示的必要任務,延遲的任務將在第一個頁面渲染完成後再進行合理的排程觸發。

·   兜底:設計兜底機制,保證程式穩定執行。

·   監控與最佳化:建立常態化監控機制,監測任務變化情況,實現精準最佳化。

由於啟動階段的任務之間存在相互依賴關係,被依賴任務會出現非同步執行未完成而導致的崩潰問題。為了解決這一問題,一種基於依賴關係來動態排程任務執行的工作管理員——《TaskManger》被設計出來。

TaskManager(後文簡稱TM)支援給任務設定執行條件,例如等待某個任務執行完成後或者某個事件發生後再開始執行;支援“關係與”依賴、“關係或”依賴,支援延時執行,支援把任務提交到主執行緒或者子執行緒執行等等。除此之外,任務之間還能傳遞資料,監聽事件等等。


Android篇 | 愛奇藝App啟動最佳化實踐分享


一、任務化

我們重新梳理了Application 階段的程式碼,並按照功能業務歸類整理,提煉出了多個任務模組。例如,我們將播放器部分的初始化工作封裝在PlayerInitTask類中。每個任務類都分為任務註冊與任務執行兩個部分,依據程式是否會啟動頁面展示,我們設定了不同的任務執行策略

PS:靈活的任務執行時機設定也是TM的一大優點。


Android篇 | 愛奇藝App啟動最佳化實踐分享

二、併發與執行緒收斂

在完成啟動業務的梳理和重構之後,將可以在子執行緒中執行的任務提交到子執行緒中執行,將之前比較耗時的任務分拆為多個子任務,阻塞併發執行,從而儘可能的充分利用CPU的算力。

並且將啟動階段的任務都對接到了TM統一排程,避免其它執行緒搶佔CPU資源以及一些不必要的系統開銷問題,完成了啟動階段執行緒的收斂。透過採取這些措施啟動階段的執行緒數明顯降低,主執行緒因為子執行緒搶佔CPU資源而導致的執行效率過低的問題也得到了解決。

Android篇 | 愛奇藝App啟動最佳化實踐分享

三、延遲

在啟動階段主要設定了兩個事件:廣告展示事件和首頁展示事件。按照業務執行的必要性,我們把啟動階段不必要執行的任務分別延遲到了這兩個階段之後執行。任務之間也按照之前梳理的依賴關係,分別設定了相應的依賴條件,解決了因被依賴任務被延遲未執行而導致的崩潰或業務異常問題。TM還 提供了一些執行監測機制,能有效避免迴圈依賴問題的發生。
由於TM的排程管理,這些任務在執行條件得到滿足後會根據當前執行條件與設定的任務優先順序等情況合理排程執行,不會出現大量任務同時併發執,從而導致頁面卡頓的問題;


四、兜底

當任務延遲後,任務執行時機存在不確定性。這可能導致在業務需要時,一些初始化任務還沒有執行完成的問題——TM 提供了任務兜底機制。
使用上面的API可以保證業務依賴的任務一定被執行,從而解決了因為“非同步”與“延遲”可能給業務帶來崩潰或者邏輯異常問題。

五、監控與最佳化

1)阻塞等待監控
由於TM提供了任務的兜底機制,理論上就會存在因業務需要而導致等待任務執行完成的場景產生。這種問題在低端裝置上更為常見。為了解決這一問題,我們在TM中新增了任務等待監控功能,將其納入常態化的監控中,並且成功發現了多項阻塞等待的問題。透過通知業務方進行邏輯最佳化,大大減少甚至避免了部分阻塞等待的問題,使用者體驗獲得了更進一步的提升。

2)啟動資料監控

我們將Lens的啟動資料投遞到後端,並且建立了啟動分析日報機制。將啟動過程分段,除了啟動時間外,還投遞了程式初始化階段、頁面建立階段、頁面渲染階段的分階段耗時資料,當某項資料明顯劣化後,服務端就會發出預警。

3)歷史版本啟動任務對比分析

目前最新的Lens 版本支援版本間啟動任務對比分析功能,我們可以在介面上展示出兩個版本之間的任務變化差異,例如新增任務、減少任務及執行耗時變化超出閾值的任務資訊。透過分析這些變化的任務資訊,就可以直接“約談”相關業務方,進而快速的完成最佳化工作。

Android篇 | 愛奇藝App啟動最佳化實踐分享

與此同時,我們團隊還執行了一些其他的最佳化手段,例如推進程式碼執行效率的最佳化、提前載入一些重要展示資料等等。

 

總結

透過多個版本的迭代,完善了任務排程框架、啟動任務常態化監控機制、任務分析功能等等。


Android篇 | 愛奇藝App啟動最佳化實踐分享

最佳化後啟動耗時與執行緒資訊(Debug)

現已經最佳化到500ms以內,啟動任務、啟動階段執行緒數也大幅度減少。在這次的最佳化實踐工作中,Lens 與TM 兩個工具發揮了重要作用。關於Lens的細節,我們將在後續進一步為大家分享。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69945252/viewspace-2669116/,如需轉載,請註明出處,否則將追究法律責任。

相關文章