一乞巧、知識點
1.1 App啟動分為冷啟動和熱啟動
- 冷啟動是指當前App的進程沒有在系統(tǒng)中,需要系統(tǒng)重新分配進程給他啟動摊鸡,是一次完整的啟動過程绽媒。
- 熱啟動是指App啟動后退到后臺,再重新進入前臺免猾。
1.2 App啟動的三個階段
- main函數執(zhí)行前
- main函數執(zhí)行后
- 首屏渲染完成后
1.3 main函數執(zhí)行前的操作
- 加載.o可執(zhí)行文件
- 加載動態(tài)庫
- Objc運行時初始化是辕,包括相關類的注冊、category注冊猎提、selector唯一性檢查
- 初始化获三,包括所有+load方法、C++靜態(tài)全局變量
1.4 main函數執(zhí)行后
main函數到appDidFinishLaunchWithOptions中首屏渲染執(zhí)行完成锨苏。
1.5 首屏渲染完成后
appDidFinishLaunchWithOptions中首屏渲染完成到方法作用域結束疙教。
1.6 優(yōu)化方案
- 功能優(yōu)化:將與首屏無關的功能放到首屏渲染完成之后再去做。
- 方法優(yōu)化:監(jiān)聽方法耗時伞租,優(yōu)化時間長的方法贞谓。
1.7 監(jiān)聽方法耗時
- 定時抓取方法堆棧,記錄時長葵诈。定時為0.01最佳裸弦。
- 對objc_messageSend方法進行hook祟同。
二、課后作業(yè)
上面提到了監(jiān)聽方法耗時的兩種方法理疙。第二種方法在戴銘老師的專欄中有詳細介紹晕城,由于能力有限,沒能弄明白沪斟。這里只實現一下第一種方法广辰。
實現思路
1.寫一個定時器,每0.01秒獲取主線程的方法堆棧主之,并記錄所有方法地址。
2.當下一次定時器獲取的方法堆棧時李根,若方法地址已經存在于記錄中槽奕,則該方法時長加0.01;若記錄中不存在房轿,則初始化方法時長為0.01粤攒。
2.1 如何獲取方法堆棧
這里推薦github上的工具輕量級調用棧分析器
我為他新加了一個方法,返回所有方法地址和方法名的鍵值對集合囱持。
// 獲取主線程方法堆棧中所有方法地址和方法名稱的集合
+ (NSArray<JCStackMethodModel *> *)bs_backtraceMapArrayOfMainThread;
2.2 如何記錄時長
記錄每次抓取到的方法并更新時長
/**
處理抓取到的方法堆棧
@param methodModels 當前定時間隔堆棧上的方法
*/
- (void)managerCurrentStackMethods:(NSArray<JCStackMethodModel *> *)methodModels {
// 查看是否在記錄中
for (JCStackMethodModel *model in methodModels) {
BOOL isExist = NO;
for (JCStackMethodModel *existModel in self.stackMethods) {
// 如果在記錄中夯接,時長+0.01
if ([model.methodAddress isEqualToString:existModel.methodAddress]) {
isExist = YES;
existModel.time += TimeTnterval;
break;
}
}
// 如果不在記錄中,加入記錄中纷妆,并初始化時長為0.01
if (!isExist) {
model.time = TimeTnterval;
[self.stackMethods addObject:model];
}
}
}
最后附上完整代碼
更多詳細內容盔几,請移步至戴銘老師的專欄