优化 App 的启动速度
App 的启动速度不仅影响我们调试,也直接关系到用户体验。之前有些很久没有打开过的项目,需要花费很长的时间才完成编译;对应的 App 在点击后,许久才出现启动画面。你是否为这些问题苦恼过呢?
这是我观看 WWDC2016 Sessions406 《Optimizing App Start Time》的博客笔记。虽然没有字幕听起来很吃力,但光看 Slide 还是有不少收获的。原文有点长,包括理论是实践两部分,为了方便阅读这里只放出一部分。
Mach-O 文件是如何被加载的
在 mian() 函数执行之前,操作系统为我们做了什么?
exec() -> main()
exec()执行过程:
内核随机分配一段可用的内存给应用程序。但有个规则,即不分配低地址的内存空间,该地址空间大小由处理器的位数决定,情况如下:
32位处理器保留 4K
64位处理器保留 4G
低地址保留,用于保存空指针、异常错误信息等。

加载动态库
内存分配完成后,处理器运行动态加载器(Dynamic loader)来加载动态依赖库(dylibs)。
加载过程:
映射所有的直接依赖库,递归间接调用的依赖库(Map all dependent dylibs,recurse).
重建所有的图片(Rebase all images).
绑定所有图片(Bind all images).
准备代码层面的加载(ObjC prepare images)
执行初始化方法(Run initializes).

直接加载:
解析所有的动态库
找出需要的 mach-O 文件
打开并读取文件
认证 mach-O 文件
登记代码签名
为每个 segment 调用
mmap()映射函数
递归加载:
当所有直接依赖库加载完毕后,还存在直接依赖库依赖于其他库的情况。递归加载间接依赖库,一般 App 需要加载 100 到 400 个动态库!其中绝大多数为系统库,苹果已经最优化了系统库的加载。
2. 重建(Rebasing)
将图片资源根据其地址进行加载,重建信息被编码在 LINKEDIT segment 中。重建的过程按照地址顺序执行,所以可以被内核预取。
3. 绑定(Binding)
应用程序对动态库的引用只是字符层(symbol)面上,绑定过程中需要加载器通过函数名来查找,相对于重建这个过程需要更多的计算。

4. ObjC 准备阶段
完成重建和绑定后的配置工作
登记定义的 ObjC 类
更新实例变量对应的内存位置
分类的方法被插入到主类
5. 初始化(Initializer)
静态分配内存的对象的初始化
调用 +load 方法
调用相关联的动态库
最后,执行 main()函数
启动优化
对于不同的设备启动速度都不相同,苹果认为完美的启动时间是在 400 毫秒以内。App 的最大允许启动时间为20秒,如果超过这个时间就会被 Killed。
我们可以通过编辑工程的 Schemes 来打印 App 的启动中各项时间花费,从而来分析和优化启动过程。
在 Arguments -> Environment Variables 中加入 DYLY_PRINT_STATISTICS。

设置后,控制台部分项时间花费输出:

1. 加载动态库
加载动态库需要很大的开销,解决方法是尽可能减少引入不必要的动态库,合并现有可操作的动态库,使用静态文件,使用懒加载等
2. 重建和绑定过程
减少指针变量的使用
减少 Objective-C 类
减少 C++ 虚基类的使用(少见)
建议使用 Swift 结构体
尽可能将属性设置为只读
3. 初始化
将
+load函数的操作尽可能在+initialize方法中执行简化 C++ 构造函数
不要在初始化方法里面调用
dlopen()不要在初始化方法里面创建线程
+initialized 会在任何类加载之前被调用,而 +load 是所在类被加载到系统的时候被调用,这通常比 +initialized 调用的时机要早。在 +load 函数里面做操作会延缓系统的启动时间。
dlopen() 函数用于打开 Bundle 尽可能的延迟读取本地的 Bundld 资源,也有利于加快启动速度。
线程的创建需要很大的开销,不要在 App 启动的过程创建子线程。
参考阅读
1. https://developer.apple.com/videos/play/wwdc2016/406/
2. http://objccn.io/issue-6-3/
3. https://code.facebook.com/posts/1675399786008080/optimizing-facebook-for-ios-start-time/
优化 App 的启动速度的更多相关文章
- Android性能优化-App启动优化
原文地址:https://developer.android.com/topic/performance/launch-time.html#common 通常用户期望app响应和加载速度越快越好.一个 ...
- 优化 App 的启动时间
这是一篇 WWDC 2016 Session 406 的学习笔记,从原理到实践讲述了如何优化 App 的启动时间. App 运行理论 main() 执行前发生的事 Mach-O 格式 虚拟内存基础 M ...
- Android性能优化-App后台优化
原文链接 Background Optimizations 前言 后台进程是内存和电池敏感的.一个隐式的broadcast可能会启动很多监听它的后台进程,即使这些进程可能做得工作不多.这可能丢设备性能 ...
- 怎样优化app,看Facebook怎样做
周四,Facebook Engineering blog 发表了一篇名为<Improving Facebook on Android>博文.博文从四个方面(Performance,Data ...
- WWDC2018 之 优化 App Assets Optimizing App Assets
该篇博客记录了观看WWDC Session227<Optimizing App Assets>的内容以及一些理解. 引言 该session主要讲述了使用Assets Catalog的新特性 ...
- 如何优化 App 的启动时间
http://www.cocoachina.com/ios/20161102/17931.html App 运行理论 main() 执行前发生的事 Mach-O 格式 虚拟内存基础 Mach-O 二进 ...
- iOS 如何优化 App 的启动时间
App 运行理论 main() 执行前发生的事 Mach-O 格式 虚拟内存基础 Mach-O 二进制的加载 理论速成 Mach-O 术语 Mach-O 是针对不同运行时可执行文件的文件类型. 文件类 ...
- [Android Memory] Android Zipalign zip对齐优化app程序
转载地址:http://www.cnblogs.com/xirihanlin/archive/2010/04/12/1710164.html 参考文章:http://www.cnblogs.com/l ...
- 5个可以帮你优化App的优秀网站
也许现在有一款App可以提供所有你需要的,你不需要的,或者你可以想象到的内容.但是,有多少App真的可以不仅满足需求而且还能提供很好的用户体验呢? 相信很多APP并没有这样的能力.有一些APP的设计特 ...
随机推荐
- mysql-python模块编译问题解决
解决方法:yum -y install mysql-devel libxml2 libxml2-dev libxslt* zlib gcc openssl [root@localhost MySQL- ...
- Axis2在Web项目中整合Spring
一.说明: 上一篇说了Axis2与Web项目的整合(详情 :Axis2与Web项目整合)过程,如果说在Web项目中使用了Spring框架,那么又改如何进行Axis2相关的配置操作呢? 二.Axis2 ...
- MYSQL数据库重点:事务与锁机制
一.事务 一组连续的数据库操作,每一次操作都成功,整个事务就成功,只要有一步出错,整个事务就失败: MySQL事务与存储引擎相关 1.MyISAM:不支持事务,用于只读程序提高性能 2.InnoDB: ...
- Codeforces 161 D. Distance in Tree (树dp)
题目链接:http://codeforces.com/problemset/problem/161/D 题意: 给你一棵树,问你有多少对点的距离为k. 思路: dp[i][j]表示离i节点距离为j的点 ...
- HTTP原理
HTTP原理 1 简介 HTTP是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统. HTTP协议的主要特点可概括如下: 1.支持客户/服务器模式. 2.简单快速:客 ...
- windows win7 win10 多系统启动菜单 多系统引导设置
win键+R 输入msconfig 根据显示的程序设置(除非你看不懂文字)
- 有关获取session属性时报nullPointException(空指针异常)的解决方案
一般我们在从session中获取数据时,需要先进行赋值,也就是必须先进行session.setAttribute(String,Object)方法进行赋值,然后我们才能从session中获取内容,但是 ...
- jQuery日历和日期选取插件
参考网站:http://developer.51cto.com/art/201103/248670.htm http://www.open-open.com/ajax/3_Calendar.htm 推 ...
- Slony-I中对storelisten出错的处理
客户质询的现象是: Slony-I运行中,log中发现FATAL信息: FATAL storeListen: unknown node ID 出现了上述错误后,再看后继的log,又恢复正常运行了. 客 ...
- 为DAG预留群集名称对象(CNO)
在某些环境中,计算机帐户的创建受到限制或计算机帐户是在非默认计算机容器中创建的,则会预留群集名称对象 (CNO),然后通过为其分配权限来设置 CNO.此外,使用运行 Windows Server 20 ...