摘要:馬蜂窩旅游歷經(jīng)幾十個版本的開發(fā)迭代,在啟動流程上積累了一定的技術(shù)債務(wù)。我們定義啟動廣告曝光率啟動廣告曝光啟動廣告加載。
增長、活躍、留存是移動 App 的常見核心指標(biāo),直接反映一款 App 甚至一個互聯(lián)網(wǎng)公司運(yùn)行的健康程度和發(fā)展動能。啟動流程的體驗(yàn)決定了用戶的第一印象,在一定程度上影響了用戶活躍度和留存率。因此,確保啟動流程的良好體驗(yàn)至關(guān)重要。
「馬蜂窩旅游」App 是馬蜂窩為用戶提供服務(wù)的主要陣地,其承載的業(yè)務(wù)模塊不斷豐富和完善,產(chǎn)品功能日趨復(fù)雜,已經(jīng)逐漸成長為一個集合旅行信息、出行決策、自由行產(chǎn)品及服務(wù)交易的一站式移動平臺。
「馬蜂窩旅游」iOS App 歷經(jīng)幾十個版本的開發(fā)迭代,在啟動流程上積累了一定的技術(shù)債務(wù)。為了帶給用戶更流暢的使用體驗(yàn),我們團(tuán)隊(duì)實(shí)施了數(shù)月的專項(xiàng)治理,也總結(jié)出一些 iOS 啟動治理方面的實(shí)踐經(jīng)驗(yàn),借由本文和大家分享。
0X0?如何定義「啟動」要分析和解決啟動問題,我們首先需要界定啟動的內(nèi)涵和邊界,從哪開始、到哪結(jié)束,中間經(jīng)歷了哪些階段和過程。以不同視角去觀察時,可以得出不同結(jié)論。
技術(shù)視角App 啟動原本就是程序啟動的技術(shù)過程。作為開發(fā)人員,我們很自然地更愿意從技術(shù)階段去看待和定義啟動的流程。
App 啟動的方式分為冷啟動和熱啟動兩種。簡單來說,冷啟動發(fā)生時后臺是沒有這個應(yīng)用的進(jìn)程的,程序需要從頭開始,經(jīng)過漫長的準(zhǔn)備和加載過程,最終運(yùn)行起來。而熱啟動則是在后臺已有該應(yīng)用進(jìn)程的情況下發(fā)生的,系統(tǒng)不需要重新創(chuàng)建和初始化。因此,從技術(shù)視角討論啟動治理時,主要針對冷啟動。
從技術(shù)視角出發(fā),分析 iOS 的啟動過程,主要分為兩個階段:
pre-main: main() 函數(shù)是程序執(zhí)行入口,從進(jìn)程創(chuàng)建到進(jìn)入 main 函數(shù)稱為 premain 階段, 主要包括了環(huán)境準(zhǔn)備、資源加載等操作;
post-main: main() 函數(shù)到-didFinishLaunchWithOptions:方法執(zhí)行結(jié)束。該階段已獲得代碼執(zhí)行控制權(quán),是我們治理的主要部分。
用戶視角?????????????????? ??+----------------X------------------------------------X---------> start?????????????main???????????????????-didFinishLaunchWithOptions:
iOS App 是面向終端用戶的產(chǎn)品,因此衡量啟動的最終標(biāo)準(zhǔn)還是要從用戶視角出發(fā)。
從用戶視角定義啟動,主要以用戶主觀視覺為依據(jù),以頁面流程為標(biāo)準(zhǔn)。這樣看來,常見的 App 啟動可以分為三個階段:
T1:閃屏頁
閃屏頁是啟動過程中的靜態(tài)展示頁。在冷啟動的過程中,App 還沒有運(yùn)行起來,需要經(jīng)歷環(huán)境準(zhǔn)備和初始化的過程。這個過渡階段需要展示一些視圖,供阻塞等待中的用戶瀏覽。
iOS 系統(tǒng) (SpringBoard) 根據(jù) App Bundle 目錄下的 Info.plist 中"Launch screen interface file base name"字段的值,找到所指定的 xib 文件,加載渲染展示該視圖。
閃屏頁的展示是系統(tǒng)行為,因此無法控制;加載的是 xib 描述文件,無法定制動態(tài)展示邏輯,因此是靜態(tài)展示。
對應(yīng)技術(shù)啟動階段的 pre-main 階段
T2(可選):歡迎頁(廣告)
App 運(yùn)行后根據(jù)特定的業(yè)務(wù)邏輯展示的第一個頁面。常見的有廣告頁和裝機(jī)引導(dǎo)流程。
歡迎頁是業(yè)務(wù)定制的,因此可根據(jù)業(yè)務(wù)需要優(yōu)化展示策略,該階段本身也是可選的。
T3:目標(biāo)頁?(落地頁)?
App 啟動的目標(biāo)頁。
可以是首頁或特定的落地頁
目標(biāo)頁的加載渲染渲染完成標(biāo)志著 T3 階段的結(jié)束,也標(biāo)志著啟動流程的結(jié)束。
啟動治理的最終目標(biāo)是提升用戶體驗(yàn),在這樣的思想下,本文關(guān)于啟動流程的討論主要圍繞用戶視角進(jìn)行。
0X1?方法論及關(guān)鍵指標(biāo) APM 方法論對 iOS 啟動的治理,本質(zhì)上是對應(yīng)用性能優(yōu)化 (App Performance Management) 的過程,其基本的方法論可以歸納為:
界定問題
準(zhǔn)確描述現(xiàn)象,確定問題的邊界
確定量化評價手段,明確關(guān)鍵指標(biāo)
分析問題
分析問題產(chǎn)生的主要原因,根本原因
確定問題的重要性,優(yōu)先級
性能問題可能是單點(diǎn)的短板,也可能是復(fù)雜的系統(tǒng)性問題,切忌「頭痛醫(yī)頭,腳痛醫(yī)腳」。要嚴(yán)謹(jǐn)全面地分析問題,找到主要原因、根本原因予以優(yōu)先解決
解決問題
確定解題的具體技術(shù)方案
根據(jù)關(guān)鍵指標(biāo)量化成果
對問題進(jìn)行總結(jié),積累沉淀
持續(xù)監(jiān)控
性能問題是持續(xù)的,長期的
對關(guān)鍵技術(shù)指標(biāo)建立長效的監(jiān)控機(jī)制,確保增量能被及時反饋,予以處理
關(guān)鍵指標(biāo)1. 啟動耗時
啟動耗時是衡量啟動性能的核心指標(biāo),因?yàn)樗苯佑绊懥擞脩趔w驗(yàn)并對用戶轉(zhuǎn)化率產(chǎn)生影響。
對啟動耗時指標(biāo)的拆解有助于細(xì)粒度地監(jiān)控啟動過程,幫助找到問題環(huán)節(jié)。具體可以拆解為:
技術(shù)啟動耗時指標(biāo)
pre-main
core-postmain
主觀啟動耗時指標(biāo)
T1_duration? :從程序運(yùn)行起點(diǎn)到主視窗可見
T2_duration
T3_duration
total_duration
根據(jù)對馬蜂窩 App 用戶的行為數(shù)據(jù)分析確認(rèn),我們得到以下結(jié)論:
啟動耗時和啟動流失率正相關(guān)
啟動耗時和次日留存負(fù)相關(guān)
2.啟動流失率
1). 如何定義啟動流失
用戶視角的啟動流程完成前(即目標(biāo)頁渲染完成前),用戶主動離開 App(進(jìn)入后臺,殺死 App, 切換到其他 App 等),記做一次啟動流失。
啟動流失率計(jì)算公式為:
啟動 PV 流失率:啟動流失 PV / App 首次進(jìn)入前臺 PV
啟動 UV 流失率:啟動流失 UV / DAU
UV 絕對流失率:當(dāng)日僅進(jìn)入前臺一次且流失的 UV / DAU
2)?如何定義首次進(jìn)入前臺
我們先來區(qū)分下冷啟動,熱啟動和首次進(jìn)入前臺的概念:
iOS App 有后臺機(jī)制,App 可在某些條件下,在用戶不感知的情況下在后臺啟動(如后臺刷新)。由于用戶不感知,如果當(dāng)日該用戶沒有主動進(jìn)入前臺,則不會記作活躍用戶。因此,單純的后臺啟動不是啟動流失率的分母。
但是當(dāng) iOS App 從后臺啟動,并留在內(nèi)存中沒有被操作系統(tǒng)清除,而一段時間后,用戶觸發(fā) App 進(jìn)入前臺,這種情況雖然是熱啟動,但應(yīng)被看作「首次進(jìn)入前臺」。
3)?如何定位流失的時機(jī)
根據(jù)定義,用戶主動離開 App 則記作一次流失。從技術(shù)角度可以找到兩個點(diǎn):
applicationdidEnterBackground
applicaitonWillTerminate
但在實(shí)踐的典型場景中我們發(fā)現(xiàn),從用戶點(diǎn)擊 Home 鍵到程序接收到-applicationdidEnterBackground 回調(diào)存在一定的時間差,該時間差會影響到流失率的判斷。
例如,用戶在時刻 0.0s 啟動 app,啟動總時長為 4.0s。用戶在時刻 3.8s 點(diǎn)擊了 home 鍵離開 App,則應(yīng)該記作 launch_leave = true。而程序在時刻 4.3s 接收到了-applicationDidEnterBackground 回調(diào),此時啟動已經(jīng)結(jié)束,獲得了啟動耗時 4.0s。通過比較 Tleave > Tlaunch_total,則錯誤地記為?launch_leave = false。
由此推測,這里的 delay 是設(shè)置靈敏度阻尼,消除用戶決策的擺動。這個延時大約在 0.5s 左右。
為了避免這個誤差,我們的解決方案是利用 inactive 狀態(tài),找到準(zhǔn)確的用戶決策起點(diǎn):
用戶即將離開前臺時,會先進(jìn)入 inactive 狀態(tài),通過-appWillResignActive:拿到?jīng)Q策起點(diǎn)的時間戳 Tdetermine
根據(jù)用戶最終決策行為,是否確實(shí)離開,再決定決策 Tdetermine 是否有效
最終根據(jù)有效的 Tdetermine 作為判斷流失行為的標(biāo)準(zhǔn),而不是-applicationdidEnterBackground 的時間點(diǎn)
3.?啟動廣告曝光率
廣告是 App 盈利的主要手段之一。廣告曝光率直接決定了廣告點(diǎn)擊消費(fèi)率;而廣告曝光 PV 和加載 PV 直接影響了廣告售價。
我們定義:啟動廣告曝光率 = 啟動廣告曝光 PV / 啟動廣告加載 PV。
其中廣告素材需要下載,素材渲染需要一定耗時,這些都會對廣告曝光率產(chǎn)生影響。進(jìn)一步來說,啟動廣告的曝光率會受到 App 啟動性能的影響,但更主要的是受緩存和曝光策略的影響,詳細(xì)闡述在下文「精細(xì)化策略」部分介紹。
0X2?iOS App 啟動優(yōu)化以上,我們對 iOS App 啟動治理的思路和關(guān)鍵指標(biāo)進(jìn)行了分析和拆解,下面來說一下從技術(shù)層面和業(yè)務(wù)層面,我們對啟動性能的優(yōu)化和流程治理分別做了哪些事情。
?一、技術(shù)啟動優(yōu)化1.?優(yōu)化pre-main
1). pre-main?主要流程分析
在進(jìn)行該階段的優(yōu)化前,我們需要對 Pre-Main 階段的過程有所了解,網(wǎng)上的文章較多,這里主要推薦兩篇 WWDC 參考文章:
App Startup Time: Past, Present, and Future(https://developer.apple.com/v...)
Optimizing App Startup Time(https://developer.apple.com/v...)
總結(jié)來看,pre-main 主要流程包括:
????1. fork 進(jìn)程
????2. 加載 executable
????3. 加載 DYLD
? ? 4. 分析依賴,迭代加載動態(tài)庫
????? ? a. rebase
????? ? b. rebind
????? ? c. 耗時多
? ? 5. 準(zhǔn)備環(huán)境
????? ? a. 準(zhǔn)備 OC 運(yùn)行時
????? ? b. 準(zhǔn)備 C++環(huán)境
? ? 6. main 函數(shù)
2).?優(yōu)化建議
盡量少使用動態(tài)庫
????? ? a. 盡量編譯到靜態(tài)庫中,減少 rebase,rebind 耗時
????? ? b.盡量合并動態(tài)庫,減輕依賴關(guān)系
控制 Class 類的數(shù)量規(guī)模
由于 selector 需要在初始化時做唯一性檢查,應(yīng)盡量減少使用
少用 initializers?
????? ? a. 嚴(yán)格控制 +load 方法使用
多用 Swift?
????? ? a. Swift 沒有運(yùn)行時
????? ? b. Swift 沒有 initializers
????? ? c. Swift 沒有數(shù)據(jù)不對齊問題
3).?性能監(jiān)控:如何獲取啟動起點(diǎn)
啟動的結(jié)束時間相對來說是比較好確定的,但如何定位啟動的起點(diǎn),是啟動監(jiān)控的一個難點(diǎn)。
對于開發(fā)環(huán)境,可以通過 Xcode 配置啟動參數(shù),獲得 pre-main 的啟動報告:
DYLD_PRINT_STATICS?=?1
對于線上環(huán)境,根據(jù) premain 主要流程的分析,我們的解決方案是:
創(chuàng)建動態(tài)庫 ABootMonitor.dylib
ABootMonitor.dylib?實(shí)現(xiàn)+load 方法,記錄啟動起點(diǎn)時間
將 ABootMonitor.dylib 放在 executable 動態(tài)庫依賴的頭部
通過上述方法,可以在線上環(huán)境盡量地模擬出最早的啟動時間點(diǎn),從而更好地監(jiān)測優(yōu)化效果。
2.?優(yōu)化post-main
post-main 階段的技術(shù)優(yōu)化主要針對兩個方法的執(zhí)行耗時來進(jìn)行:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:
- (void)applicationDidBecomeActive:(UIApplication *)application;
為什么包含 2,需要我們對 iOS App 生命周期有一定理解。從操作系統(tǒng)的視角來看,iOS App 本質(zhì)上是一個進(jìn)程。對于 Mac OS/iOS 系統(tǒng),進(jìn)程的生命周期狀態(tài)包括了:
not-running
running?
進(jìn)程激活,可以運(yùn)行的狀態(tài)
suspend?
進(jìn)程被掛起,不可以執(zhí)行代碼,通常在 UIApplication 進(jìn)入后臺后一段時間被系統(tǒng)掛起
zombie?
進(jìn)程回收前的臨時狀態(tài),很短暫
terminated?
進(jìn)程終止,并被清理
而對于 UIApplication,定義了生命周期狀態(tài):
//??UIApplication.h typedef?NS_ENUM(NSInteger,?UIApplicationState)?{ ????UIApplicationStateActive,?????//?前臺,?UIApplication響應(yīng)事件 ????UIApplicationStateInactive,???//?前臺,?UIApplication不響應(yīng)事件 ????UIApplicationStateBackground??//?后臺,?UIApplication不在屏幕上顯示 }?NS_ENUM_AVAILABLE_IOS(4_0);
組合起來的狀態(tài)機(jī)如下圖:
通過上面的討論,我們可以分析出以下問題:
UIApplication 會因?yàn)槟撤N原因,在用戶不感知的情況下被喚起,進(jìn)程進(jìn)入 running 狀態(tài),但停留在 iOS 的 background 狀態(tài)
每次冷啟動都會執(zhí)行- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:,但未必進(jìn)入前臺
在 didFinishLaunchingWithOptions 中進(jìn)行大量 UI 和網(wǎng)絡(luò)請求等操作是不合理
post-main?優(yōu)化思路和建議
整理拆分啟動項(xiàng),以啟動項(xiàng)為粒度進(jìn)行測量
啟動項(xiàng)執(zhí)行盡量在背景線程
啟動的過程 CPU 占用較高,占用主線程會導(dǎo)致卡頓,耗時延長,用戶體驗(yàn)不佳
啟動項(xiàng)并發(fā)執(zhí)行
啟動項(xiàng)延遲執(zhí)行
當(dāng) CPU 時間片跑滿時,使用多線程并發(fā)不能提高性能,反而會因?yàn)轭l繁的線程上下文切換,造成 overhead 耗時增長
盡可能將啟動項(xiàng)延遲執(zhí)行,在時間軸上平滑,降低 CPU 利用率峰值
啟動項(xiàng)分組
-didFinishLaunchingWithOptions 只執(zhí)行必要的核心啟動項(xiàng)
其他啟動項(xiàng),在首次調(diào)用-applicationDidBecomeActive:后執(zhí)行
二、精細(xì)化策略1. 交互優(yōu)化
通過技術(shù)的實(shí)現(xiàn)手段,我們可以從客觀上減少啟動的絕對耗時。而從用戶視角來看,對于啟動是否流暢會受到很多心理因素的主觀影響。因此從另一方面,我們可以從優(yōu)化交互的角度提升用戶體驗(yàn)。
避免阻塞等待
我們都希望用戶可以盡快地使用 App,不要出現(xiàn)流失。但在快消費(fèi)的時代,用戶的耐心是極其有限的。
因此,如果有理由需要用戶進(jìn)行等待,就應(yīng)該注意盡量避免產(chǎn)品流程是阻塞的。即使有更充足的理由必須讓用戶在阻塞狀態(tài)原地等待,也應(yīng)該給用戶提供可響應(yīng)的交互。
例如,在 T2 歡迎/廣告頁階段,為了避免用戶阻塞等待,應(yīng)該提供明顯的「跳過」按鈕,允許用戶進(jìn)行跳過操作。
如果非要用戶在這個階段等待不可,也可以花一些小心思提供可響應(yīng)的交互,比如點(diǎn)擊觸發(fā)視覺的變化等,不要讓用戶除了等待無事可做。
增加視覺信息量
增加屏幕上視圖的信息量提供給用戶消費(fèi),轉(zhuǎn)移其注意力,降低用戶對等待的感受。
例如,在 T1 閃屏頁階段,用戶處于阻塞等待的狀態(tài),無法跳過。而且閃屏頁是系統(tǒng)渲染的靜態(tài)視圖,我們無法提供動態(tài)響應(yīng)。那么,我們可以通過在靜態(tài)視圖上提供更多信息量,給等待中的用戶消費(fèi)。
主觀感受對比如下圖:
合理的動態(tài)提示
合適的動畫
事實(shí)上,早期在部分高性能 Android 設(shè)備上,App 的啟動比同水平 iDevice 要快。但由于 iOS 設(shè)計(jì)了符合神經(jīng)認(rèn)知學(xué)的交互動畫,使得主觀感受到的時間縮短。
動畫是否「合適」,關(guān)鍵在于對場景的選擇和數(shù)量的把握。一個常見的動畫耗時約為 0.25s,對于啟動流程來說,已經(jīng)可以解決或掩蓋不少問題了。
合適的提示信息
好的交互體驗(yàn)和產(chǎn)品流程,至少應(yīng)該是符合用戶預(yù)期的。給以合適的動態(tài)提示,讓用戶知道此刻使用的 App 正在發(fā)生什么,可以極大地提升用戶體驗(yàn)。
例如在 T2 廣告頁階段,廣告需要占時 3 秒鐘的時間。交互上建議給與廣告消失的倒計(jì)時提示:
一方面,倒計(jì)時提示可以有動態(tài) loading 的視覺效果,展現(xiàn) App 的良好運(yùn)行;
另一方面,倒計(jì)時可以讓用戶安心,主觀上耗時減少,情緒上不至于焦慮和退出。
2.?基于場景的啟動會話
根據(jù)對啟動過程的定義,我們可以列舉出一些啟動的「起點(diǎn)」和「終點(diǎn)」,比如:
啟動觸發(fā)點(diǎn):
點(diǎn)擊 App 圖標(biāo)正常啟動
初次安裝
點(diǎn)擊 PUSH 進(jìn)入
應(yīng)用間跳轉(zhuǎn)
3DTouch
Siri 喚起
其他
啟動終點(diǎn)--目標(biāo)頁:
應(yīng)用首頁
指定的落地頁
可以看出,啟動的起點(diǎn)和終點(diǎn)多種多樣,而對于啟動流程的設(shè)定,很多都是和業(yè)務(wù)場景強(qiáng)相關(guān)的,比如:
初次安裝需要進(jìn)入裝機(jī)引導(dǎo)流程
正常啟動需要展示廣告
PUSH 進(jìn)入可以不展示廣告,直達(dá)落地頁
其他
如何才能維護(hù)這些復(fù)雜的啟動關(guān)系,提高業(yè)務(wù)承載能力呢?我們的優(yōu)化思路是基于場景創(chuàng)建啟動會話:
由啟動參數(shù)和其他條件確定啟動場景
根據(jù)啟動場景創(chuàng)建具體的啟動會話
啟動會話接管之后的啟動流程
3.?啟動廣告曝光和緩存策略
廣告曝光主要流程為:請求廣告接口 —> 準(zhǔn)備廣告素材 —> 展示廣告頁,進(jìn)行曝光。
在準(zhǔn)備廣告素材環(huán)節(jié),我們會判斷廣告素材是否命中緩存。如果命中則直接使用緩存,這樣可以明顯縮短廣告加載的時間。如果沒有命中,則開始下載廣告素材。當(dāng)廣告素材超過設(shè)定的準(zhǔn)備時長,則此次曝光不顯示。
通過以往數(shù)據(jù)量化分析,我們發(fā)現(xiàn)通常情況下,廣告未曝光的主要原因是由于廣告素材準(zhǔn)備超時,且素材體積和廣告曝光率是負(fù)相關(guān)的。為了保證廣告的曝光率,我們應(yīng)該盡量減少廣告素材的體積,并且提高廣告素材緩存的命中率。
下面分別介紹下我們的啟動廣告預(yù)緩存策略和啟動廣告曝光策略。
啟動廣告預(yù)緩存策略
廣告素材接口和廣告曝光接口分離
在可能的合適時機(jī),下載廣告素材
??????例如后臺啟動,后臺刷新等
盡可能地提前下發(fā)廣告素材
拉長廣告素材投放的時間窗口
常見地可提前半月下發(fā)廣告素材
對于「雙十一等大促活動,應(yīng)盡早地下發(fā)素材
啟動廣告曝光策略
分級的廣告曝光QoS策略
???????若業(yè)務(wù)許可,可對廣告優(yōu)先級進(jìn)行分級
對于低優(yōu)先級,應(yīng)用 cache-only 的曝光策略
對于普通優(yōu)先級,應(yīng)用 max-wait 的曝光策略
對于高優(yōu)先級,應(yīng)用 max-retry 的曝光策略
靈活的曝光時機(jī)選擇
通常我們僅在首次進(jìn)入前臺時,進(jìn)行廣告曝光,但這有一定的缺陷:
啟動耗時長了,用戶體驗(yàn)差,啟動流失率高
對于當(dāng)日只有一次啟動且啟動流失的用戶,丟了這個 DAU
我們可以在 App 首次進(jìn)入前臺,和熱啟動切回前臺時選擇時機(jī),進(jìn)行有策略的曝光
可依據(jù)策略,在首啟時不展示廣告頁,提升用戶體驗(yàn),DAU,減少啟動流失
可在 App 切回時展示,提升廣告曝光 PV,和曝光率。
由于 App 之前已經(jīng)啟動,此時大概率已經(jīng)緩存了廣告素材
由于 App 一次生命周期存在多次切回前臺,曝光 PV 可以得到提升
根據(jù)馬蜂窩 App 的統(tǒng)計(jì)分析,在激進(jìn)策略下可提升曝光 PV 約 4 倍
三、合理利用平臺機(jī)制iOS 經(jīng)過多年的迭代,提供了很多智能的平臺機(jī)制。合理利用這些機(jī)制,可以強(qiáng)化 App 的功能和性能。
1.?內(nèi)存保活
我們已經(jīng)討論了冷啟動和熱啟動的區(qū)別:
冷啟動是進(jìn)程并不存在的狀態(tài),一切需要從 0 開始。
熱啟動是指進(jìn)程在內(nèi)存中(iOS 不支持 SWAP),此時可能處于 background 的 running 狀態(tài)或 suspend 狀態(tài),用戶喚起進(jìn)去前臺。
熱啟動可以極大地減少 T1 閃屏頁時間,從而減少啟動耗時。
因此,我們應(yīng)該盡量增加熱啟動概率,并且盡量減少 App 在后臺被系統(tǒng)回收的概率。
iOS App 生命周期中關(guān)于系統(tǒng)內(nèi)回收策略如下:
App 進(jìn)入后臺后,進(jìn)程會活躍一段時間后,會被操作系統(tǒng)掛起,進(jìn)入 suspend 狀態(tài)。除非在 info.plist 指定進(jìn)入后臺即退出。
前臺運(yùn)行的 App 擁有內(nèi)存的優(yōu)先使用權(quán)
當(dāng)前臺的 App 需要更多物理內(nèi)存時,系統(tǒng)根據(jù)一定策略,將一部分掛起的 App 進(jìn)行釋放
系統(tǒng)優(yōu)先選擇占用內(nèi)存多的 App 進(jìn)行釋放
優(yōu)化思路:
App 進(jìn)入后臺時,應(yīng)該將內(nèi)存資源竟可能的釋放,盡量在內(nèi)存中保活
尤其對于可重得的圖片,文件等資源進(jìn)行釋放
對于可持久化的非重要內(nèi)存,也可做持久化后釋放
對于線上,應(yīng)利用后臺進(jìn)程激活狀態(tài),加強(qiáng)對后臺內(nèi)存使用的監(jiān)控
2.?后臺拉起
iOS 系統(tǒng)提供了一些機(jī)制,可以幫助我們實(shí)現(xiàn)在用戶不感知的情況下拉起 App。合適的拉起策略,可以優(yōu)化 App 性能和功能表現(xiàn),比如提升當(dāng)日首啟熱啟動的概率;在后臺準(zhǔn)備更新一些數(shù)據(jù),如更新 PUSH token、準(zhǔn)備啟動廣告素材等。
iOS 常見的后臺拉起機(jī)制包括:
Background-fetch 后臺刷新
需要權(quán)限
在某特定時機(jī)拉起,智能策略
PUSH?
靜默推送
遠(yuǎn)端推送
aps 中指定 "content-available = 1"
App 實(shí)現(xiàn)相關(guān)處理方法
地理圍欄
后臺網(wǎng)絡(luò)任務(wù) NSURLBackgroundSession
VOIP 等其他
使用后臺機(jī)制時,有以下幾點(diǎn)需要注意:
常見的后臺機(jī)制需要 entitlement 聲明和用戶授權(quán)
部分節(jié)能模式會使部分拉起機(jī)制失效,導(dǎo)致節(jié)能量模式不可用
拉起策略參考用戶意圖,用戶主動殺死 App,會使部分拉起機(jī)制失效
正常進(jìn)入后臺,該 App 會向系統(tǒng)應(yīng)用「AppSwitcher」注冊,并受其管理
如果用戶主動殺死 App,該 App 不會向「AppSwitcher」注冊
后臺拉起時,主要從 AppSwitcher 的注冊列表選擇 App 進(jìn)行操作。例如,后臺刷新會根據(jù)某種策略排序,依此拉起 AppSwitcher 中注冊的部分 App
批量拉起會導(dǎo)致服務(wù)端接口壓力過大
例如使用 PUSH 拉起,則短時間內(nèi)可能有數(shù)千萬的 App 被拉起,此時接口請求不亞于一次針對服務(wù)端的 DDOS 攻擊,需要整理和優(yōu)化
四、結(jié)構(gòu)化定制頁面棧/樹優(yōu)化
App 通過頁面進(jìn)行組織,在啟動過程中,我們需要構(gòu)建根頁面棧。
由上分析我們知道,App 存在后臺拉起,我們建議在首次進(jìn)入前臺時才進(jìn)行頁面渲染操作。但另一方面,根頁面棧是 App 的基本結(jié)構(gòu),應(yīng)該作為核心啟動流程。因此我們提出以下解決方案:
涉及啟動的頁面,如首頁、落地頁等,應(yīng)將頁面棧創(chuàng)建、數(shù)據(jù)請求、頁面渲染分離
在核心啟動流程 (didFinishLaunch) 創(chuàng)建核心頁面棧
在即將進(jìn)入前臺時,異步請求數(shù)據(jù)
在目標(biāo)頁即將展示時,進(jìn)行渲染
例如,在廣告頁消失前的 1s,通知首頁進(jìn)行渲染,如下圖
由于目標(biāo)頁可能和 T2 等啟動階段重疊,應(yīng)特別注意頁面加載的性能問題,避免交叉影響
0x3?結(jié)語經(jīng)過團(tuán)隊(duì) 3 個月的持續(xù)優(yōu)化治理,馬蜂窩 iOS App 的啟動優(yōu)化取得了一些成果:
啟動耗時:約 3.6s,減少約 50%
PV啟動流失率:降低約 30%
啟動廣告曝光率:大幅提升
ios App 的啟動治理乃至性能管理,是一個長期且艱巨的過程,需要各位開發(fā)同學(xué)具備良好的對平臺和對代碼性能的理解意識。其次,性能問題也常常是一個復(fù)雜的系統(tǒng)性問題,需要嚴(yán)謹(jǐn)?shù)胤治龊屯评恚诖烁兄x支持以上工作的馬蜂窩數(shù)據(jù)分析師。最后,這項(xiàng)工作需要建立完善的性能監(jiān)控機(jī)制,持續(xù)跟蹤,主動解決。
One?More Thing?我們計(jì)劃于近期將馬蜂窩 iOS 的啟動框架開源,歡迎持續(xù)關(guān)注馬蜂窩公眾號動態(tài)。期待和大家交流。
本文作者:許旻昊,馬蜂窩 iOS 研發(fā)技術(shù)專家。
(馬蜂窩技術(shù)原創(chuàng)內(nèi)容,轉(zhuǎn)載務(wù)必注明出處保存文末二維碼圖片,謝謝配合。)
關(guān)注馬蜂窩技術(shù)公眾號,找到更多你需要的內(nèi)容
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/110222.html
摘要:本文將結(jié)合馬蜂窩容器化平臺賦能前端應(yīng)用構(gòu)建的實(shí)踐經(jīng)驗(yàn),介紹整個平臺背后的設(shè)計(jì)和實(shí)現(xiàn)原理,取得的一些效果及問題的優(yōu)化方案。如果使用容器化平臺就不會出現(xiàn)這方面的擔(dān)憂。 容器對前端開發(fā)真的有用嗎?答案是肯定的。 最初當(dāng)我向公司的前端同學(xué)「安利」容器技術(shù)的時候,很多人都會說:「容器?這不是用在后端的技術(shù)嗎?我不懂啊,而且前端開發(fā)用不上吧。」 showImg(https://segmentfau...
摘要:本文將結(jié)合馬蜂窩容器化平臺賦能前端應(yīng)用構(gòu)建的實(shí)踐經(jīng)驗(yàn),介紹整個平臺背后的設(shè)計(jì)和實(shí)現(xiàn)原理,取得的一些效果及問題的優(yōu)化方案。如果使用容器化平臺就不會出現(xiàn)這方面的擔(dān)憂。 容器對前端開發(fā)真的有用嗎?答案是肯定的。 最初當(dāng)我向公司的前端同學(xué)「安利」容器技術(shù)的時候,很多人都會說:「容器?這不是用在后端的技術(shù)嗎?我不懂啊,而且前端開發(fā)用不上吧。」 showImg(https://segmentfau...
摘要:本文將結(jié)合馬蜂窩容器化平臺賦能前端應(yīng)用構(gòu)建的實(shí)踐經(jīng)驗(yàn),介紹整個平臺背后的設(shè)計(jì)和實(shí)現(xiàn)原理,取得的一些效果及問題的優(yōu)化方案。如果使用容器化平臺就不會出現(xiàn)這方面的擔(dān)憂。 容器對前端開發(fā)真的有用嗎?答案是肯定的。 最初當(dāng)我向公司的前端同學(xué)「安利」容器技術(shù)的時候,很多人都會說:「容器?這不是用在后端的技術(shù)嗎?我不懂啊,而且前端開發(fā)用不上吧。」 showImg(https://segmentfau...
閱讀 894·2021-09-03 10:42
閱讀 1511·2019-08-30 15:56
閱讀 1444·2019-08-29 17:27
閱讀 869·2019-08-29 15:25
閱讀 3156·2019-08-26 18:27
閱讀 2479·2019-08-26 13:41
閱讀 1888·2019-08-26 10:39
閱讀 1569·2019-08-23 18:36