IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> iOS启动优化之——如何使用Xcode Log、App Launch、代码来计算启动时间 Launch Time -> 正文阅读

[移动开发]iOS启动优化之——如何使用Xcode Log、App Launch、代码来计算启动时间 Launch Time

iOS启动优化之——如何使用MetricKit 来计算启动时间 Launch Time
,我们提到,可以使用MetricKit 在Organizer中或者直接代码统计,那么还能用什么来统计呢?

配置环境变量打印

Xcode曾经提供了一些环境变量比如DYLD_PRINT_STATISTICS来提供时间统计(参考Xcode 动态库环境变量——不止DYLD_PRINT_STATISTICS),我们在Scheme的Run 环境变量中添加该参数,启动之后,Xcode会在log中打印如下内容:

Total pre-main time: 821.85 milliseconds (100.0%)
         dylib loading time: 379.71 milliseconds (46.2%)
        rebase/binding time: 147.25 milliseconds (17.9%)
            ObjC setup time:  48.93 milliseconds (5.9%)
           initializer time: 245.95 milliseconds (29.9%)
           slowest intializers :
             libSystem.B.dylib :   4.40 milliseconds (0.5%)
    libMainThreadChecker.dylib :  30.37 milliseconds (3.6%)
                          **** : 342.37 milliseconds (41.6%)

但是在iOS15之后,iOS 15 and macOS Monterey have a new version of dyld 参考: DYLD_PRINT_STATISTICS not working / Xcode 13.0 beta / iOS 15.0 beta 8

我们就需要使用App launch工具来计算

Instrument App Launch

首先,我们打开AppLaunch工具, Xcode -> Open Development Tools -> Instrument,App Launch可以检查安装在手机上的Debug或者Release 版本的App,我们选择好对应的项目

如果是Debug的App,最好是选择Debug下也支持DWARF with DSYM File,这样一旦有比较耗时的函数,我们也可以通过Time Profile发现,我后面也会展示如何定位

选择好使用的App,我们打开App Launch的开始键,App会被启动,待启动过后我们在点击下停止,则App Launch 就会开始分析

请添加图片描述

结果过下,可以看到紫色、绿色、蓝色的色块,分别对应了不同的阶段
请添加图片描述

  • 紫色 Initialize相关
  • 绿色 Launch 相关
  • 蓝色 应用已激活
  • 灰色 没有该App的执行工作
  • 橙色 被更高级别的线程打断
  • 红色 因为缺少CPU资源而没有执行

我们继续查看下面更详细的统计信息,先看下表格内容,截图如下:

在这里插入图片描述

Start	Duration	Narrative	
00:00.000.000	72.37 ms	The system took 72.37 ms to create the process.	
00:00.072.374	19.19 ms	The system frameworks took 19.19 ms to initialize.	
00:00.091.561	10.25 ms	Initializing – Static Runtime Initialization	
00:00.103.011	31.62 ms	Launching – UIKit Initialization	
00:00.134.632	427.29 μs	Launching – UIKit Scene Creation	
00:00.135.059	5.37 ms	Launching – UIKit Scene Creation	
00:00.140.426	1.14 ms	Launching – didFinishLaunchingWithOptions()	
00:00.141.565	9.32 ms	Launching – UIKit Scene Creation	
00:00.150.883	345.42 μs	Launching – Initial Frame Rendering	
00:00.152.563	2.08 s	Currently running in the foreground...	

可以看到,这里的每部分内容都对应着火焰图中的不同色块,本次初始化耗时150ms

那么,我们增加一个耗时操作,然后尝试找到它,这里用一个经典案例,就是初学者经常用同步的方法来加载远程图片

if let url = URL(string: "https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7dafb64bc6844d66adb8a12dd7690855~tplv-k3u1fbpfcp-zoom-crop-mark:3024:3024:3024:1702.awebp?") {
        let data = try? Data(contentsOf: url)
        print("download")
    }

将这行代码放到didfinishLaunch中执行,看下测试结果请添加图片描述
本次启动已经从0.15s 增加到了1.3s左右,如何查看下是哪个函数导致呢? 我们选择Time Profile,然后尝试查找可能的函数,结果如下图所示,找到了Data.init(contentOf:Options)方法

请添加图片描述

AppLaunch 的使用细节可以参考 使用Instruments了解iOS应用启动时长(Xcode13)

代码打印

如果要使用代码计算,我们这里使用sysctl 函数获取线程的初始化时间,然后计算当前时间差获取启动时间

这里引用抖音的文章内容来说明计算具体时机,我也会在后面的文章中解释时机问题

既然要监控,那么就要能够在代码里获取到启动时长。启动的起点大家采用的方案都一样:进程创建的时间。
启动的终点对应用户感知到的Launch Image消失的第一帧,抖音采用的方案如下:
iOS 12及以下:root viewController的viewDidAppear
iOS 13+:applicationDidBecomeActive
Apple官方的统计方式是第一个CA::Transaction::commit,但对应的实现在系统框架内部,抖音的方式已经非常接近这个点了。

代码实现如下:

class LaunchTime: NSObject {
    static func processStartTime() -> TimeInterval {

        var kinfo = kinfo_proc()
        var size = MemoryLayout<kinfo_proc>.stride
        var mib: [Int32] = [CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()]
        sysctl(&mib, u_int(mib.count), &kinfo, &size, nil, 0)
        let startTime = kinfo.kp_proc.p_starttime
        return TimeInterval(startTime.tv_sec) + TimeInterval(startTime.tv_usec) / 1e6
    }

    class func launchTime() -> String {
        let begin = processStartTime()
        let now = Date().timeIntervalSince1970
        
        let launch = now - begin
        let launchstring = "\(launch)"
        return launchstring
    }
}
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-07-20 19:00:48  更:2022-07-20 19:02:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 3:53:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码