作者 / Google 和 Facebook 團隊
撰稿 / Google Android 團隊的 Kateryna Semenova 和 Facebook 團隊的 Tim Trueman、Steven Harris、Subramanian Ramaswamy
簡介
縮短應用的啟動時間並非小事,我們必須深入瞭解其影響因素。今年,Google Android 團隊和 Facebook 應用團隊一直在合作研究這方面的量化指標,並共享優化方法,以改善應用啟動情況。Google Android 的公開文件中包含了很多關於 應用啟動優化 的資訊。這裡我們想進一步分享其在 Facebook 應用中的實踐情況,以及哪些因素有助於改善應用啟動效能。
現在,每個月有超過 29 億人使用 Facebook。Facebook 幫助人們構建社群,並讓世界更緊密地聯絡在一起。使用者會在這裡分享生活的瞬間,瞭解和討論正在發生的事情,建立和培養人際關係,共同合作以創造收入機會。
Facebook 應用開發者則致力於確保使用者享受最佳體驗,並讓應用在任意裝置、任何國家/地區和不同網路條件下都能流暢執行。Google Android 團隊和 Facebook 團隊精誠合作,在應用啟動時間的指標定義和最佳實踐上達成共識,並在這裡分享給大家。
從哪裡開始
首先自然是測量應用的啟動時間。您可藉此獲悉使用者啟動體驗的健康程度,追蹤啟動時間惡化的情況,並計算進行改進需要投入的資源量。歸根結底,您的啟動時間需要與使用者滿意度、參與度或使用者增長相關聯,以確定投入的優先次序。
Android 定義了兩個衡量應用啟動時間的指標: 完全顯示所用時間 (TTFD) 和 初步顯示所用時間(TTID)。雖然您可以進一步將其劃分為冷/暖啟動時間,但本文不會解釋它們之間的區別,而 Facebook 的方法是,衡量和優化與應用互動的所有使用者所經歷的啟動時間 (有些是冷啟動,有些是暖啟動)。
完全顯示所用時間 (Time-To-Full-Display, TTFD)
TTFD 會記錄您的應用完成渲染並可供使用者互動和使用時所需的時間,可能包括顯示本地儲存或來自網路上的內容所需的時間。如果網路較慢,這可能會花費一段時間,並會視使用者的使用裝置而有所差異。因此,我們有必要立即展示一些內容,讓使用者看到應用啟動的程式,而這就要提到 TTID 了……
初步顯示所用時間 (Time-To-Initial-Display, TTID)
TTID 會記錄您的應用顯示背景、導航、可快速載入的本地內容、載入較慢的本地或網路內容的佔位塊所需要的時間。TTID 應該是使用者可以四處導航並前往其目標的所需時間。
不要改變太多: 有一件事需要注意,就是在 TTID 和 TTFD 之間應用內容的視覺變化問題,例如在頁面裡先展示的是已快取的內容,然後在網路內容載入完成後突然切換頁面內容。這種突然的變化可能會讓使用者感到不快和沮喪,所以請確保您的應用可在 TTID 期間顯示足夠有意義的內容,儘可能地向使用者展示其將在 TTFD 期間看到的內容。
達成使用者目標
使用者訪問您的應用是為了獲取內容,這可能需要一段時間完成載入,而您希望應用可以儘快把這些內容呈現給他們。
Facebook 應用開發者專注於基於 完全顯示所用時間 (TTFD) 的指標,包含顯示所有內容和影像,因為這代表了使用者訪問應用的完整體驗。開發者想要知道,網路載入內容和影像是否花費了較長時間,或者載入失敗,以便讓團隊可以從頭到尾改善整個啟動體驗。
良好的 TTID 和 TTFD 目標應當是多少?
Facebook 將啟動時間指標設定為他們認為應用啟動耗時 "不佳" 的百分比,即任何 TTFD 超過 2.5 秒的啟動或啟動失敗的部分 (例如,影像無法載入或應用崩潰)。Facebook 致力於通過改進時間超過 2.5 秒的啟動,使其擺脫 "不佳" 狀態,以及修復導致啟動失敗的問題,從而降低啟動時間 "不佳" 的比例。選擇 2.5 秒是因為,研究表明,這對於 Facebook 使用者來說很重要。這也與 Web Vitals 為網站建議的 最大內容繪製 (LCP) 指標相符。
與 TTID 相比,提供完整體驗,尤其是用網路獲取最近的內容,會讓您的 TTFD 啟動指標看起來相當緩慢。而這其實是一件好事!它反映了使用者對您應用的真實體驗。您對此所做的改進,可能會像 Facebook 那樣,提高使用者的應用使用率以及對其效能的認可。
測量 TTFD 的棘手程度可能會視您的應用而異。如果太難,不妨從 初步顯示所用時間 (TTID) 著手。雖然由於佔位塊或影像的存在可能會導致無法量化部分內容的載入效能,但這依然是一個著手點,畢竟這部分也是使用者日常與應用互動的內容 (雖然不是全部)。
檢測 TTID
在 Android 4.4 (API 級別 19) 及更高版本中,logcat 提供了 "Displayed" 值,用於記錄從啟動程式到完成在螢幕上繪製相應 Activity 第一幀所經過的時間。
報告的日誌行類似於以下示例:
ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms
檢測 TTFD
要檢測 TTFD,只需在您的所有內容都在螢幕上顯示後,在 Activity 中呼叫 reportFullyDrawn())。請確保包含替換佔位符的任何內容,以及您渲染的任何影像 (務必計算影像本身顯示的時間,而不僅是其佔位符顯示的時間)。在您呼叫 reportFullyDrawn() 後,就可以在 logcat 裡看到它:
ActivityManager: Fully drawn {package}/.MainActivity: +1s54ms
來自 Facebook 應用開發者的建議
多年來,Facebook 應用開發者一直在為眾多裝置、平臺以及國家/地區的數十億使用者優化應用。本節分享了 Facebook 應用開發者在優化應用啟動時運用的一些關鍵經驗。
- 先理解,再優化 - 在定義了好的啟動指標後,您就應該用其檢測應用的具體表現,這有助於理解應用的啟動效能並設定改進優先順序,為您的使用者帶來更好的體驗。從量化檢測入手,一來可以證明存在提升空間,二來可以確定重點努力的方向,並且在開始優化後能看到具體的改進效果。
- 首先修復崩潰 - 在您檢測啟動狀況之後,請確保應用確實可以啟動。啟動時的崩潰是最讓人沮喪的事情,也是讓使用者放棄您應用的最快方式,請優先判定和處理這些問題。
- 切莫忘記功能可靠性 - 另外,不要忘記功能可靠性。您的應用是否能迅速展示一些內容,但卻未能載入所有內容,或者載入影像的耗時過長?您的應用可能啟動得很快,但未能按使用者要求執行 (比如,點選按鈕不起作用),這些因素都會惡化使用者體驗。
- 以一致性為目標 - 與具備一致性但啟動時間長於平均水平的效能表現相比,不一致的效能表現更令人沮喪。觀察啟動時間的長尾,檢視是否存在緩解這些啟動緩慢情況的修復措施或方法。請務必檢視您的離線和有損網路啟動效能的啟動行為。
- 並行工作 - 大多數當代手機都有至少 4 個 CPU,所以有空間處理多工!除非萬不得已,否則不要阻塞主執行緒。將 I/O 和非關鍵路徑移動到主執行緒之外執行。
- 延遲執行 - 在實現了可靠且一致的啟動後,請檢視您為顯示首個可見畫面的內容所做的一切,是否有一些工作是不必要的?在應用啟動之後,請把與啟動體驗不直接相關的任何工作移除、延後、或者移到後臺 (但是注意觀察應用的響應能力,並將其作為一個控制指標)。試著讓您應用的 onCreate() 儘量保持輕量。您還可使用 Jetpack App Startup 開發庫,以便在應用啟動時初始化元件。這樣做時,請確保仍然載入所有啟動活動所需的模組,並且注意在延遲載入的模組可用時不要造成閃爍。
- 顯示進度,但是不要過多地改變介面 - 請不要在啟動期間過度改變要展示給使用者的內容。如果使用者嘗試點選內容,結果它卻發生變化,並得到了錯誤的結果,這是十分令人沮喪的。這類似於 Web Vitals 中的 累積佈局偏移 (CLS) 概念。對於時長不定的網路端載入,請略過啟動畫面,並顯示非同步載入的佔位符。您可以考慮在這個內容區域使用不太顯眼的 動畫 來反映載入狀態。確保具體載入的內容結構和佔位結構儘可能地匹配,以便在內容載入完成後實現平滑過渡。
- 快取 - 當使用者第一次開啟應用時,您可以為一些介面元素展示載入指示器。在使用者下次訪問您的應用時,您可在載入更多最新內容的同時,顯示這些已快取的內容。您是否曾在應用載入完成後,看到我們在 Facebook 的動態更新中展示從網路獲取到的最新內容?如果可以,請將網路載入過程從啟動中排除出去,這樣可以加快速度,並實現更一致的啟動效能體驗。但是,正如下一點所建議的那樣,顯示已快取的內容並不總是最佳做法,因此,我們要衡量並找到對使用者更友好的要素。
- 快慢結合 - 新穎,相關,但顯示速度稍慢的內容,比快速顯示的過時內容更好。直接向您的使用者展示最新的內容,比啟動超級迅速,但在啟動不久之後就得重新整理內容要更有價值。您可以評估以下做法是否效果更好: 做出優化,以儘量快速地顯示最新內容,並設定超時時間,以在網路較慢時顯示較舊的內容;在網路離線時,直接顯示既有的內容。
- 一致的會話開始介面 - 在您的應用長時間處於後臺後,您可能會發現,將使用者重置到您的主內容介面是很好的做法。應用可以在裝置的記憶體中保留很長時間。
- 檢視內部工作原理 - 如果您 跟蹤 並切實檢視了啟動期間執行的內容,或者乾脆使用偵錯程式,您可能會有讓人驚喜的新發現!在充分了解了啟動的關鍵路徑後,您就可以高效地優化應用效能。在發現了具有最大提升空間的要素後,就在該方面做出投入。
- 確保能輕鬆實現正確的結果 - 開發者有時會使用並非最優的模式和架構,因為做事情的方法太多了。請放心大膽地整合您應用中使用的模式,然後加以優化,以便輕鬆選擇合適方法,從而完成任務並讓其高效執行。即時程式碼執行 (eager code execution) 模式就是一個很好的例子: 如果您正在執行第一次全屏繪製後才需要出現的內容程式碼,那麼效能表現肯定會遭受損害。您不妨採用延遲執行的模式,僅在啟動的關鍵路徑遭到阻塞時,再以即時執行方式執行程式碼。
Google Android 團隊給出的建議
Google Android 團隊關於衡量和優化應用啟動的建議請查閱官方文件 "應用啟動時間"。
本節總結了一些適用於所有 Android 應用開發者且與上述 Facebook 建議相關的要點。
- TTID 和 TTFD 是應用啟動的重要指標。Google Android 會在 Play 管理中心 按照 TTID 對應用進行排名。TTFD 是 TTID 的母集,因此 TTID 的任何改進措施都同時適用於這兩個指標。
- 呼叫 reportFullyDrawn() 來報告 TTFD,讓系統知道 Activity 已完成渲染。為改善應用啟動速度,Android 系統會進行調整,以優先處理在呼叫 reportFullyDrawn()) 之前發生的工作。在您的應用處於完全可用狀態時呼叫這個方法可以改善應用的啟動時間。每個應用都應該使用這個 API!切莫忘記用其衡量應用表現情況。
- 用 Android Vitals 監控您應用的技術效能,有助於改善應用啟動體驗。通過 Play 管理中心,您可以檢視各種資料以幫助您瞭解和改進應用的啟動時間等效能表現。
- 我們知道,與在開發階段修復錯誤相比,生產環境中的修復成本要高得多。這點也同樣適用於效能方面。您可以藉助 Jetpack Macrobenchmark: Startup 設定您的應用,以在早期使用本地效能測試衡量應用啟動情況。
- 正如我們上面討論的那樣,量化檢測是瞭解和優化啟動的關鍵。Android 提供 系統跟蹤 服務,可以幫助深入挖掘和診斷應用啟動問題。
- 通過 Jetpack App Startup 開發庫,我們可以直接高效地在應用啟動時初始化元件。開發庫和應用的開發者都可以使用此庫來簡化啟動流程,並明確地設定初始化順序。您可以使用此庫設定在啟動期間的什麼時刻載入哪些元件。
- 影響應用啟動的一個 典型問題 是在初始化時做了太多工作。比如,填充過大或複雜的佈局、阻止螢幕繪製、載入和解碼點陣圖、垃圾回收等。
總結
本文介紹了一些關鍵的啟動時間指標和優化最佳實踐,以改善啟動體驗,幫助提升 Facebook Android 應用的使用者參與度和使用率。本文還分享了 Google Android 團隊建議的指標、開發庫和工具。任何 Android 應用都可從本文分享的策略中受益。請大家動起手來,認真量化應用的啟動情況,併為使用者打造快速且令人愉悅的應用啟動體驗!
歡迎您 點選這裡 向我們提交反饋,或分享您喜歡的內容、發現的問題。您的反饋對我們非常重要,感謝您的支援!