随着项目越做越大,代码和业务量越来越多,这时候每次启动APP的时候就会花费较长的时间,这对用户来说体验很不好。所以,针对APP启动时间的优化还是很有必要的。

关于APP启动时间的分析和优化可以以main()为分界点,分为main()方法执行之前的加载时间(pre-main time)和main()之后的加载时间。那么,如何定量的测量这两个阶段具体的执行时间呢,下面先给出测量方法,看一下自己项目启动时间是否合理:

一、main()方法之前启动时间的测量方法:

在Xcode中添加环境变量参数DYLD_PRINT_STATISTICS即可,这样运行APP时在控制台就会打印出pre-main花费的时间,如下图:

如果想打印详细的pre-main中各个过程花费的时间,可以再添加一个DYLD_PRINT_STATISTICS_DETAILS参数,这时你会看到pre-main time和total time的值不一样,其实下边的total time - debugger pause time就和上边的pre-main time大概一致了。如下图:

PS:如果你想打印dyld装载动态库的顺序,可以设置这个环境变量 DYLD_PRINT_LIBRARIES

二、main()方法之后的启动时间的测量方法:

在main.m文件中,定义一个全局变量:

CFAbsoluteTime startTime;int main(int argc, char * argv[]) {startTime = CFAbsoluteTimeGetCurrent();

在AppDelegate.m文件中didFinishLaunchingWithOptions方法return之前计算时间差:

 double launchTime = CFAbsoluteTimeGetCurrent() - startTime;NSLog(@"launchTime = %f秒",launchTime);

三、main()方法调用之前启动过程的解析:

App开始启动后,系统内核(XNU)首先加载可执行文件(自身App的所有.o文件的集合),然后加载动态链接器dyld,dyld是一个专门用来加载动态链接库的库。 执行从dyld开始,dyld从可执行文件的依赖开始, 递归加载所有的依赖动态链接库。

补充:用户点击图标之后,会发送一个系统调用 execve 到内核,内核创建进程。接着会把主二进制 mmap 进来,读取 load command 中的 LC_LOAD_DYLINKER,找到 dyld 的的路径。然后 mmap dyld 到虚拟内存,找到 dyld 的入口函数_dyld_start(最终调到dyld的_main函数),把 PC 寄存器设置成_dyld_start,接下来启动流程交给了 dyld。)

动态链接库包括:iOS 中用到的所有系统 framework,加载OC runtime方法的libobjc,系统级别的libSystem,例如libdispatch(GCD)和libsystem_blocks (Block)。

总结来说,main()方法调用前,启动过程大体分为如下步骤:

1、内核加载可执行文件

2、load dylibs image (加载程序所需的动态库镜像文件)

3、Rebase image /  Bind image (由于ASLR(address space layout randomization)的存在,可执行文件和动态链接库在虚拟内  存中的加载地址每次启动都不固定,所以需要修复镜像中的资源指针)

4、Objc setup (注册Objc类、将Category中的方法插入方法列表)

5、initializers (调用Objc类的+load()方法、调用C++类的构造函数)

针对上边各个启动过程,我们可以做的优化有:

1、减少动态库的引用,将项目中不使用的Framework及时删除,将Xcode配置中General -> Linked Frameworks and Libraries中使用不到的系统库不再引用。

2、合并动态库。

3、尽量不使用内嵌(embedded)的dylib,加载内嵌dylib性能开销较大。

4、清理项目中冗余的类、category。对于同一个类有多个category的,建议进行合并。

5、将不必须在+load方法中做的事情延迟到+initialize中。

6、尽量不要用C++虚函数(创建虚函数表有开销),不要在C++构造函数中做大量耗时操作。

四、main()方法调用之后过程的解析:

main()方法调用之后,主要是didFinishLaunchingWithOptions方法中初始化必要的服务,显示首页内容等操作。这时候我们可以做的事情主要有:

1、将一些不影响首页展示的服务放到其他线程中去处理,或者延时处理和懒加载。延时处理可以监听Runloop的状态,当进入kCFRunLoopBeforeWaiting(即将休眠状态)再去处理任务,最大限度的利用CPU等系统资源。

2、使用Xcode的Instruments的Time Profiler工具,分析启动过程中比较耗时的方法和操作,然后,进行具体的优化。

3、重点关注TabBarController和首页的性能,保证尽快的能展示出来。这两个控制器及里边的view尽量用代码进行布局,不使用storyboard和xib,如果在布局上想更进一步的优化,那就连autolayout(Massonry)都不要使用,直接使用frame进行布局。

4、本地缓存。首页的数据离线化,优先展示本地缓存数据,等待网络数据返回之后更新缓存并展示。

以上就是关于iOS客户端启动优化的相关总结,如有不同意见或者更好的方案,欢迎沟通交流。

参考:

iOS启动时间优化

今日头条iOS客户端启动速度优化

iOS App从点击到启动(介绍系统架构和底层知识较多)

APP从编译到链接再到启动的过程

2022年更新:

抖音品质建设 - iOS启动优化之原理篇_字节跳动技术团队官方博客-CSDN博客

iOS启动速度优化总结相关推荐

  1. iOS启动速度优化实践分享

    一款App的启动速度,不单单只有用户体验这一方面,往往还决定了它能否收获更多的用户.这就好像陌生人第一次碰面,第一感觉往往决定了他们接下来是否会继续交往.由此可见,启动速度的优化必然是App开发过程中 ...

  2. iOS 性能优化总结

    原文链接:https://github.com/skyming/iOS-Performance-Optimization 关于 iOS 性能优化梳理: 基本工具.业务优化.内存优化.卡顿优化.布局优化 ...

  3. 关于iOS应用启动速度优化

    前言 不积跬步,无以至千里;不积小流,无以成江海.--荀子 关于App应用启动速度优化的话题:Session 406 Optimizing App Startup Time ,该Session上App ...

  4. 抖音品质建设 - iOS启动优化《实战篇》

    前言 启动是 App 给用户的第一印象,启动越慢,用户流失的概率就越高,良好的启动速度是用户体验不可缺少的一环.启动优化涉及到的知识点非常多,面也很广,一篇文章难以包含全部,所以拆分成两部分:原理和实 ...

  5. 爱奇艺技术分享:爱奇艺Android客户端启动速度优化实践总结

    本文由爱奇艺技术团队原创分享,原题<爱奇艺Android客户端启动优化与分析>. 1.引言 互联网领域里有个八秒定律,如果网页打开时间超过8秒,便会有超过70%的用户放弃等待,对Andro ...

  6. Android启动速度优化

    欢迎访问我的个人网站:https://coderyuan.com 最近做了一些Android App启动速度的优化,有一些心得,整理整理 影响启动速度的原因 高耗时任务 数据库初始化.某些第三方框架初 ...

  7. 抖音品质建设 - iOS启动优化之原理篇

    前言 启动是 App 给用户的第一印象,启动越慢用户流失的概率就越高,良好的启动速度是用户体验不可缺少的一环.启动优化涉及到的知识点非常多面也很广,一篇文章难以包含全部,所以拆分成两部分:原理和实战. ...

  8. iOS 滑动性能优化

    iOS 滑动性能优化 目录 一. 减少图层的Blend操作 1. UIView的背景色避免使用clearColor 2. 控件贴图避免使用带alpha的图片 3. UIImageView 使用时避免半 ...

  9. Android内核开发:系统启动速度优化

    在学习新知识的过程中,我一直很推荐结合实战任务去学习,只有经历实战,才能加深对理论知识的理解.<Android内核开发>系列已经写了八篇了,本文就结合前面的内容,给大家布置一个实战任务:  ...

最新文章

  1. [POI2009]KAM-Pebbles BZOJ1115 [ 待填坑 ] 博弈
  2. GAN的理解与TF的实现
  3. 《迷人的8051单片机》----3.4 程序
  4. github命令行操作
  5. 创业者:创业要疯狂融资要理性
  6. AndroidStudio 3.0升级之compile、implementation简要说明
  7. STM32 设置片外SRAM分散加载
  8. Codeforces Round #263 (Div. 2) D. Appleman and Tree 树形dp
  9. c#用canny算子做边缘提取_干货 | 边缘检测
  10. Linux下启动、停止J2SE程序(脚本)
  11. server端多个文件的压缩 .NET
  12. some any oracle,Oracle Any/Some运算符
  13. 加快pip下载的速度---镜像
  14. masscan for windows windows编译masscan
  15. Power BI Desktop 中的数据源
  16. Android Studio 4.0 新建项目gradle依赖base sdk以后报错 ‘assets/cfg/*‘ collided 的解决办法
  17. 我的世界我服务器注册密码大全,我的世界国际版账号密码大全2021
  18. django {%url %}传递参数 url 传参 报错
  19. mysql三m架构为什么_AnalyticDB for MySQL 3.0 技术架构解析
  20. 向腾讯企业邮箱发送邮件失败,报错: 559

热门文章

  1. cross-entropy for one-stage detecor
  2. 对发了offer,而没有来入职的应聘者,现在再次来应聘,如果你是面试官,你会录用吗?...
  3. 关于装有WIN7系统的硬盘转移到USB3.0移动硬盘盒后开机启动蓝屏(代码7B)的解决方案
  4. Linux NTP时钟同步
  5. 风雨十年路,历历在眼前,今做离职语,感慨有万千!-------来自一位中兴长天java十年的总工程师
  6. 基于centos 安装配置环境
  7. Linux下Socket网络编程之点对点聊天室
  8. 用‘+‘替换字符串中的所有空格[复制]
  9. websphere mq 8死信队列测试--队列满了场景
  10. 爱尔康与好大夫在线达成合作​;武田达泽优获批进入中国 | 跨国药企在中国...