【iOS開發】一個簡單、易用、強大的 iOS APP 冷啟動耗時分析工具

語言: CN / TW / HK

AMKLaunchTimeProfiler
—— 簡單、易用、強大的 iOS APP 冷啟動耗時分析工具

CI Status Version License Platform

注:以下內容,可查閱 GitHub 中 AMKLaunchTimeProfiler 的 Readme.md 以獲取及時更新,和更好的閱讀體驗~~

1、Features

  • 零成本使用: 通過 CocoaPods 一行程式碼接入,即可實現 APP 冷啟動耗時統計,包括 pre-mainmain首屏渲染三個階段的耗時,及總耗時
  • 視覺化檢視: 內建日誌檢視頁面,並自動高亮高耗時方法,各種資訊一目瞭然
  • 源資料匯出: 可以方便的通過郵件、AirDrop 等方式 匯出全部資料,具體包括
    • 日誌列表的文字資料,方便在電腦上檢視
    • 日誌的JSON資料,方便基於日誌的執行時間、呼叫方法、執行耗時 等資訊 做自定義分析
    • 多次有效資料的平均數 資料

| 31287f21b40610de7ca62a16bbcbe05f | 14448cdb434da423818f6b819ec96591 | ea4fb8a570ac2cf9769654c1ad51da1e | 4f6414aa477ba5588ffe200f3cec6e7e | fd7727cbed7e363acd8dffdd01f2e860 | | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | | 視覺化檢視 | 操作選項 | 源資料匯出 | 通過郵件匯出 | 通過其他方式匯出 |

2、Installation

AMKLaunchTimeProfiler 可通過CocoaPods完成引入,僅需現在工程的Podfile檔案中 新增如下程式碼

pod 'AMKLaunchTimeProfiler'

然後在終端在Podfile檔案所在路徑下執行 pod install命令即可完成原始碼下載與引入。

詳見:https://github.com/AndyM129/AMKLaunchTimeProfiler

3、Usage

3.1、檢視相關日誌

內建日誌檢視頁面,並自動高亮高耗時方法,各種資訊一目瞭然,具體可通過如下方式開啟:

3.1.1、使用手勢

通過 AMKLaunchTimeProfiler.debugEnable = YES; 啟用除錯模式(預設不啟用),即可在 任意介面,通過「雙指從右向左輕掃」的手勢開啟

3.1.2、使用編碼

通過 [AMKLaunchTimeProfilerLogsViewController.new presentingWithAnimated:YES completion:nil]; 使用程式碼開啟

每一次啟動,都會新建立 並儲存一個 AMKLaunchTimeProfiler 例項,相關日誌也都會存在該例項中,並實時持久化到本地,舉例如下:

```

AMKLaunchTimeProfiler id: 5c39904610203e20d26a22969df37bf9 AMKLaunchTimeProfiler version: 1.0.0 Bundle id: io.github.andym129.amk-launch-time-profiler Bundle short Version: 1.0 Bundle version: 1.0 Client Version: (null) Device Version: iPhone 11 Pro Max with iOS 15.5 Device Name: Andy's iPhone 11 Pro Max


        process-start time: 2022-06-22 16:13:00
      total time consuming: 2.121 s 
   pre-main time consuming: 1.716 s (80.88%)
       main time consuming: 0.345 s (16.24%)

first screen time consuming: 0.061 s (2.87%)


⏱ +1.716 s ~Δ 1716 ms >> INTERNAL: process-start time: 2022-06-22 16:13:00 ⏱ +1.716 s ~Δ 0 ms >> INTERNAL: main time: 2022-06-22 16:13:02 ⏱ +2.023 s ~Δ 308 ms >> -[AMKAppDelegate application:didFinishLaunchingWithOptions:]_block_invoke Line 18: 開始... ⏱ +2.026 s ~Δ 2 ms >> -[AMKRootViewController viewDidLoad]_block_invoke Line 40: 開始... ⏱ +2.044 s ~Δ 18 ms >> -[AMKRootViewController viewDidLoad]_block_invoke_2 Line 45: 結束 ⏱ +2.060 s ~Δ 16 ms >> -[AMKAppDelegate application:didFinishLaunchingWithOptions:] Line 25: hello ⏱ +2.060 s ~Δ 0 ms >> -[AMKAppDelegate application:didFinishLaunchingWithOptions:] Line 26: world ⏱ +2.060 s ~Δ 0 ms >> -[AMKAppDelegate application:didFinishLaunchingWithOptions:]_block_invoke_4 Line 36: 結束 ⏱ +2.061 s ~Δ 1 ms >> INTERNAL: did finish launching time: 2022-06-22 16:13:02 ⏱ +2.063 s ~Δ 3 ms >> -[AMKHomeViewController viewDidLoad]_block_invoke Line 38: 開始... ⏱ +2.064 s ~Δ 1 ms >> -[AMKHomeViewController viewDidLoad]_block_invoke_2 Line 42: 結束 ⏱ +2.121 s ~Δ 57 ms >> -[AMKHomeViewController viewDidAppear:]_block_invoke Line 51: 開始... ⏱ +2.121 s ~Δ 0 ms >> -[AMKHomeViewController viewDidAppear:]_block_invoke_2 Line 52: 結束 ⏱ +2.121 s ~Δ 0 ms >> -[AMKRootViewController viewDidAppear:]_block_invoke Line 54: 開始... ⏱ +2.121 s ~Δ 0 ms >> -[AMKRootViewController viewDidAppear:]_block_invoke_2 Line 55: 結束 ⏱ +2.121 s ~Δ 0 ms >> INTERNAL: first screen time: 2022-06-22 16:13:02 ⏱ +2.121 s ~Δ 0 ms >> INTERNAL: ---------------------------------------------------------------------- ⏱ +2.121 s ~Δ 0 ms >> INTERNAL: total time consuming: 2.121 s ⏱ +2.121 s ~Δ 0 ms >> INTERNAL: pre-main time consuming: 1.716 s (80.88%) ⏱ +2.121 s ~Δ 0 ms >> INTERNAL: main time consuming: 0.345 s (16.24%) ⏱ +2.121 s ~Δ 0 ms >> INTERNAL: first screen time consuming: 0.061 s (2.87%) ⏱ +2.121 s ~Δ 0 ms >> INTERNAL: ---------------------------------------------------------------------- ⏱ +11.081 s ~Δ 8960 ms >> -[AMKViewController viewDidLoad]_block_invoke Line 38: 開始... ⏱ +11.082 s ~Δ 0 ms >> -[AMKViewController viewDidLoad]_block_invoke_2 Line 41: 結束 ⏱ +11.099 s ~Δ 17 ms >> -[AMKViewController viewDidAppear:]_block_invoke Line 50: 開始... ⏱ +11.099 s ~Δ 0 ms >> -[AMKViewController viewDidAppear:]_block_invoke_2 Line 51: 結束 ```

3.2、匯出日誌

在日誌檢視頁面,點選右上角的“···”,點擊發送,即可選擇“郵件”或“其他”方式匯出,具體包括:

3.2.1、log 檔案

```

AMKLaunchTimeProfiler id: 77949e4c840246c4ddedce31d8b9b54e AMKLaunchTimeProfiler version: 1.0.0 Bundle id: io.github.andym129.amk-launch-time-profiler Bundle short Version: 1.0 Bundle version: 1.0 Client Version: (null) Device Version: iPhone 11 Pro Max with iOS 15.5 Device Name: Andy's iPhone 11 Pro Max


        process-start time: 2022-06-22 16:04:53
      total time consuming: 3.081 s 
   pre-main time consuming: 2.575 s (83.59%)
       main time consuming: 0.000 s (0.00%)

first screen time consuming: 0.000 s (0.00%)


⏱ +2.575 s ~Δ 2575 ms >> INTERNAL: process-start time: 2022-06-22 16:04:53 ⏱ +2.576 s ~Δ 0 ms >> INTERNAL: main time: 2022-06-22 16:04:56 ⏱ +3.081 s ~Δ 506 ms >> INTERNAL: first screen time: 2022-06-22 16:04:56 ⏱ +3.081 s ~Δ 0 ms >> INTERNAL: ---------------------------------------------------------------------- ⏱ +3.081 s ~Δ 0 ms >> INTERNAL: total time consuming: 3.081 s ⏱ +3.081 s ~Δ 0 ms >> INTERNAL: pre-main time consuming: 2.575 s (83.59%) ⏱ +3.081 s ~Δ 0 ms >> INTERNAL: main time consuming: 0.000 s (0.00%) ⏱ +3.081 s ~Δ 0 ms >> INTERNAL: first screen time consuming: 0.000 s (0.00%) ⏱ +3.081 s ~Δ 0 ms >> INTERNAL: ----------------------------------------------------------------------

====================================================================== AMKLaunchTimeProfiler id: 5c39904610203e20d26a22969df37bf9 AMKLaunchTimeProfiler version: 1.0.0 Bundle id: io.github.andym129.amk-launch-time-profiler Bundle short Version: 1.0 Bundle version: 1.0 Client Version: (null) Device Version: iPhone 11 Pro Max with iOS 15.5 Device Name: Andy's iPhone 11 Pro Max


        process-start time: 2022-06-22 16:13:00
      total time consuming: 2.121 s 
   pre-main time consuming: 1.716 s (80.88%)
       main time consuming: 0.345 s (16.24%)

first screen time consuming: 0.061 s (2.87%)


⏱ +1.716 s ~Δ 1716 ms >> INTERNAL: process-start time: 2022-06-22 16:13:00 ⏱ +1.716 s ~Δ 0 ms >> INTERNAL: main time: 2022-06-22 16:13:02 ⏱ +2.023 s ~Δ 308 ms >> -[AMKAppDelegate application:didFinishLaunchingWithOptions:]_block_invoke Line 18: 開始... ⏱ +2.026 s ~Δ 2 ms >> -[AMKRootViewController viewDidLoad]_block_invoke Line 40: 開始... ⏱ +2.044 s ~Δ 18 ms >> -[AMKRootViewController viewDidLoad]_block_invoke_2 Line 45: 結束 ⏱ +2.060 s ~Δ 16 ms >> -[AMKAppDelegate application:didFinishLaunchingWithOptions:] Line 25: hello ⏱ +2.060 s ~Δ 0 ms >> -[AMKAppDelegate application:didFinishLaunchingWithOptions:] Line 26: world ⏱ +2.060 s ~Δ 0 ms >> -[AMKAppDelegate application:didFinishLaunchingWithOptions:]_block_invoke_4 Line 36: 結束 ⏱ +2.061 s ~Δ 1 ms >> INTERNAL: did finish launching time: 2022-06-22 16:13:02 ⏱ +2.063 s ~Δ 3 ms >> -[AMKHomeViewController viewDidLoad]_block_invoke Line 38: 開始... ⏱ +2.064 s ~Δ 1 ms >> -[AMKHomeViewController viewDidLoad]_block_invoke_2 Line 42: 結束 ⏱ +2.121 s ~Δ 57 ms >> -[AMKHomeViewController viewDidAppear:]_block_invoke Line 51: 開始... ⏱ +2.121 s ~Δ 0 ms >> -[AMKHomeViewController viewDidAppear:]_block_invoke_2 Line 52: 結束 ⏱ +2.121 s ~Δ 0 ms >> -[AMKRootViewController viewDidAppear:]_block_invoke Line 54: 開始... ⏱ +2.121 s ~Δ 0 ms >> -[AMKRootViewController viewDidAppear:]_block_invoke_2 Line 55: 結束 ⏱ +2.121 s ~Δ 0 ms >> INTERNAL: first screen time: 2022-06-22 16:13:02 ⏱ +2.121 s ~Δ 0 ms >> INTERNAL: ---------------------------------------------------------------------- ⏱ +2.121 s ~Δ 0 ms >> INTERNAL: total time consuming: 2.121 s ⏱ +2.121 s ~Δ 0 ms >> INTERNAL: pre-main time consuming: 1.716 s (80.88%) ⏱ +2.121 s ~Δ 0 ms >> INTERNAL: main time consuming: 0.345 s (16.24%) ⏱ +2.121 s ~Δ 0 ms >> INTERNAL: first screen time consuming: 0.061 s (2.87%) ⏱ +2.121 s ~Δ 0 ms >> INTERNAL: ---------------------------------------------------------------------- ⏱ +11.081 s ~Δ 8960 ms >> -[AMKViewController viewDidLoad]_block_invoke Line 38: 開始... ⏱ +11.082 s ~Δ 0 ms >> -[AMKViewController viewDidLoad]_block_invoke_2 Line 41: 結束 ⏱ +11.099 s ~Δ 17 ms >> -[AMKViewController viewDidAppear:]_block_invoke Line 50: 開始... ⏱ +11.099 s ~Δ 0 ms >> -[AMKViewController viewDidAppear:]_block_invoke_2 Line 51: 結束

====================================================================== AMKLaunchTimeProfiler id: 554b38e7f43a36526d5b74484930d2ad AMKLaunchTimeProfiler version: 1.0.0 Bundle id: io.github.andym129.amk-launch-time-profiler Bundle short Version: 1.0 Bundle version: 1.0 Client Version: (null) Device Version: iPhone 11 Pro Max with iOS 15.5 Device Name: Andy's iPhone 11 Pro Max


        process-start time: 2022-06-22 16:26:05
      total time consuming: 2.896 s 
   pre-main time consuming: 2.263 s (78.14%)
       main time consuming: 0.563 s (19.43%)

first screen time consuming: 0.070 s (2.43%)


⏱ +2.263 s ~Δ 2263 ms >> INTERNAL: process-start time: 2022-06-22 16:26:05 ⏱ +2.263 s ~Δ 0 ms >> INTERNAL: main time: 2022-06-22 16:26:07 ⏱ +2.791 s ~Δ 529 ms >> -[AMKAppDelegate application:didFinishLaunchingWithOptions:]_block_invoke Line 18: 開始... ⏱ +2.795 s ~Δ 4 ms >> -[AMKRootViewController viewDidLoad]_block_invoke Line 40: 開始... ⏱ +2.812 s ~Δ 17 ms >> -[AMKRootViewController viewDidLoad]_block_invoke_2 Line 45: 結束 ⏱ +2.825 s ~Δ 13 ms >> -[AMKAppDelegate application:didFinishLaunchingWithOptions:] Line 25: hello ⏱ +2.825 s ~Δ 0 ms >> -[AMKAppDelegate application:didFinishLaunchingWithOptions:] Line 26: world ⏱ +2.825 s ~Δ 0 ms >> -[AMKAppDelegate application:didFinishLaunchingWithOptions:]_block_invoke_4 Line 43: 結束 ⏱ +2.825 s ~Δ 1 ms >> INTERNAL: did finish launching time: 2022-06-22 16:26:08 ⏱ +2.829 s ~Δ 3 ms >> -[AMKHomeViewController viewDidLoad]_block_invoke Line 37: 開始... ⏱ +2.829 s ~Δ 1 ms >> -[AMKHomeViewController viewDidLoad]_block_invoke_2 Line 41: 結束 ⏱ +2.896 s ~Δ 66 ms >> -[AMKHomeViewController viewDidAppear:]_block_invoke Line 50: 開始... ⏱ +2.896 s ~Δ 0 ms >> -[AMKHomeViewController viewDidAppear:]_block_invoke_2 Line 51: 結束 ⏱ +2.896 s ~Δ 0 ms >> -[AMKRootViewController viewDidAppear:]_block_invoke Line 54: 開始... ⏱ +2.896 s ~Δ 0 ms >> -[AMKRootViewController viewDidAppear:]_block_invoke_2 Line 55: 結束 ⏱ +2.896 s ~Δ 0 ms >> INTERNAL: first screen time: 2022-06-22 16:26:08 ⏱ +2.896 s ~Δ 0 ms >> INTERNAL: ---------------------------------------------------------------------- ⏱ +2.896 s ~Δ 0 ms >> INTERNAL: total time consuming: 2.896 s ⏱ +2.896 s ~Δ 0 ms >> INTERNAL: pre-main time consuming: 2.263 s (78.14%) ⏱ +2.896 s ~Δ 0 ms >> INTERNAL: main time consuming: 0.563 s (19.43%) ⏱ +2.896 s ~Δ 0 ms >> INTERNAL: first screen time consuming: 0.070 s (2.43%) ⏱ +2.896 s ~Δ 0 ms >> INTERNAL: ---------------------------------------------------------------------- ```

3.2.2、txt檔案

``` 2 次有效資料的平均數:


      total time consuming: 2.508 s 
   pre-main time consuming: 1.989 s (79.30%)
       main time consuming: 0.454 s (18.08%)

first screen time consuming: 0.066 s (2.61%) ```

3.2.3、json檔案

json // 如下內容,已做精簡 [ { "mainTimeConsuming" : 0, "bundleId" : "io.github.andym129.amk-launch-time-profiler", "didFinishLaunchingTime" : 0, "identifier" : "77949e4c840246c4ddedce31d8b9b54e", "mainTime" : 1655885096.369308, "preMainTimeConsuming" : 2.5754809379577637, "deviceVersion" : "iPhone 11 Pro Max with iOS 15.5", "processStartTime" : 1655885093.7938271, "totalTimeConsuming" : 3.0812058448791504, "deviceName" : "Andy's iPhone 11 Pro Max", "logs" : [ { "timeDelta" : 2.5753798484802246, "function" : "__INTERNAL__", "line" : 0, "timeInterval" : 2.5753798484802246, "string" : "process-start time: 2022-06-22 16:04:53" }, ... ], "bundleName" : "AMKLaunchTimeProfiler_Example", "version" : "1.0.0", "firstScreenTimeConsuming" : 0, "bundleVersion" : "1.0", "firstScreenTime" : 1655885096.8750329, "bundleShortVersion" : "1.0" }, { "mainTimeConsuming" : 0.3446040153503418, "bundleId" : "io.github.andym129.amk-launch-time-profiler", "didFinishLaunchingTime" : 1655885582.4769759, "identifier" : "5c39904610203e20d26a22969df37bf9", "mainTime" : 1655885582.1323719, "preMainTimeConsuming" : 1.7158448696136475, "deviceVersion" : "iPhone 11 Pro Max with iOS 15.5", "processStartTime" : 1655885580.416527, "totalTimeConsuming" : 2.1213448047637939, "deviceName" : "Andy's iPhone 11 Pro Max", "logs" : [ { "timeDelta" : 1.7157728672027588, "function" : "__INTERNAL__", "line" : 0, "timeInterval" : 1.7157728672027588, "string" : "process-start time: 2022-06-22 16:13:00" }, ... ], "bundleName" : "AMKLaunchTimeProfiler_Example", "version" : "1.0.0", "firstScreenTimeConsuming" : 0.060895919799804688, "bundleVersion" : "1.0", "firstScreenTime" : 1655885582.5378718, "bundleShortVersion" : "1.0" }, { "mainTimeConsuming" : 0.56263923645019531, "bundleId" : "io.github.andym129.amk-launch-time-profiler", "didFinishLaunchingTime" : 1655886368.1614871, "identifier" : "554b38e7f43a36526d5b74484930d2ad", "mainTime" : 1655886367.5988479, "preMainTimeConsuming" : 2.2627308368682861, "deviceVersion" : "iPhone 11 Pro Max with iOS 15.5", "processStartTime" : 1655886365.336117, "totalTimeConsuming" : 2.8956289291381836, "deviceName" : "Andy's iPhone 11 Pro Max", "logs" : [ { "timeDelta" : 2.2626559734344482, "function" : "__INTERNAL__", "line" : 0, "timeInterval" : 2.2626559734344482, "string" : "process-start time: 2022-06-22 16:26:05" }, ... ], "bundleName" : "AMKLaunchTimeProfiler_Example", "version" : "1.0.0", "firstScreenTimeConsuming" : 0.070258855819702148, "bundleVersion" : "1.0", "firstScreenTime" : 1655886368.231746, "bundleShortVersion" : "1.0" } ]

3.3、自定義日誌

對於耗時較高的方法,可以通過補充自定義日誌的方式,輔助找出具體的耗時的操作,進而通過優化 實現提速冷啟動,相關方法如下:

```objective-c /// 列印日誌

define AMKLaunchTimeProfilerLog(FORMAT, ...);

/// 列印日誌 - @"開始..."

define AMKLaunchTimeProfilerLogBegin(FORMAT, ...);

/// 列印日誌 - @"結束"

define AMKLaunchTimeProfilerLogEnd(FORMAT, ...);

/// 列印日誌 - 內部日誌

define AMKLaunchTimeProfilerInternalLog(FORMAT, ...);

/// 列印日誌 - 相同位置 只打一次

define AMKLaunchTimeProfilerOnceLog(FORMAT, ...);

/// 列印日誌 - 相同位置 只打一次 - @"開始..."

define AMKLaunchTimeProfilerOnceLogBegin(FORMAT, ...);

/// 列印日誌 - 相同位置 只打一次 - @"結束"

define AMKLaunchTimeProfilerOnceLogEnd(FORMAT, ...);

/// 完全自定義的日誌 - (void)logWithFunction:(const char _Nullable)function line:(NSInteger)line string:(NSString _Nullable)format, ...;

```

4、Author

5、License

AMKLaunchTimeProfiler is available under the MIT license. See the LICENSE file for more info.


注:以上內容,可查閱 原文 以獲取及時更新,和更好的閱讀體驗~~