【学习总结】02 | App 启动速度怎么做优化与监控?
1、前言
首先,我认为学习总结,要有所总,所结,就是有归纳后,能用自己的话
告诉别人!有所结,就是有所收获输出,一般我认为是思维导图
,所以,每篇文章前,我都会先给出文章的脑图:
2、正文
注意,本系列总结不会引用或提供原课程文章所有的内容或代码,只会作出思维导图,需要学习可购买课程 《iOS开发高手课 - 极客时间》
本文作为第一篇,脑图中包含了一些学习的方法论,这里就不展开了,具体可以查看 如何建立你自己的开发知识体系 | iHTCboy's blog
学习原则
授人以鱼不如授人以渔
就想学习英语一样,每一个字母都认识,但是串联起来就不认识了。学习也一样,可能整篇文章大家都看懂
了,但是对于其中的词语或句子,可能是不懂的,比如,rebase 指针
、attribute((constructor))
、selector 唯一性检查
、动态库加载
、ReactiveCocoa框架
、抓取主线程调用栈
、Mach-O
、lazy 和 non-lazy 符号
、rebind_symbol
、等。或者,整篇文章都没有看懂
,但是每个字都认识。
第一种情况,对于不认识的关键字,在搜索引擎就能找到很多,只能说是懒或恐惧心态,让你永远不去了解。第二种情况,一般多见于是抽象的文章,比如项目架构、编程思想等,大家都懂 MVC
/MVVM
,就是说不出懂什么的感觉,这种情况,还是建议多广义的学习,更多的实践,很多东西,还是较难做到言传,只能意会!
还有一种情况,我认为就是文章大家都看懂了,也没有什么疑问,但是忽略了一个面的概念,把问题想太简单
,不会把知识点串联起来,不会触类旁通、融会贯通。举个例子,做过开发的都应该知道单例模式
,如果不知道,搜索引擎都能搜索出一堆教程,并且介绍了来由,用途等,大家就知了知了。操作系统任务管理器、回收站、文件系统是不是一个单例?数据库连接池呢?生活中的例子,比如主席、CTO,对一个国家或一个公司,都是唯一的。
所以,第三种情况,目前来看大多数人看文章学习都达不到的层次,需要借助大量的阅读或别人的传授或指点,才能悟出来。所以,这就是我要说的,授人以鱼不如授人以渔
,尽自己最大的已知学习和分享,这是一件快乐的事~
启动
-
冷启动
App 点击启动前,它的进程不在系统里,需要系统新创建一个进程分配给它启动的情况。这是一次完整的启动过程。 -
热启动
App 在冷启动后用户将 App 退后台,在 App 的进程还在系统里的情况下,用户重新启动进入 App 的过程,这个过程做的事情非常少。
文章中简单的提到了冷启动
、热启动
。可能大家也是一看而过。这个启动其实是很重要的概念,不知道大家有没有留意,汽车发动机的冷启动和热启动
、电脑的冷启动和热启动
?那么,手机是不是也有冷启动和热启动?iOS有冷启动和热启动,那么Android是不是也有冷启动和热启动?那么App有冷启动和热启动,那么微信的小程序是不是也有冷启动和热启动?
答案是肯定的!它们都有!为什么呢???似乎所有的系统都有冷启动和热启动!那么,冷启动和热启动,那么对汽车的伤害更大吗?冷启动和热启动那个对性能损耗(消耗)更大呢?答案也是肯定的,是冷启动
!
我是希望通过这个例子,让大家更加明白,一个简单的概念,可能很普通,但是一定不要放过!那么,到这里,针对App 启动速度怎么做优化
,冷启动和热启动的重要性是不是自然而然就出来了,我们应该关注 App的冷启动和热启动,减少冷启动,尽量让App在后台时能通过热启动打开。
,怎么理解呢?对于 iOS,系统严管管控手机的内存,当发现内存不足时,系统会全局发通知,让大家把不要的内存释放出来,如果大家都不释放,后台的应用就会被干掉,当然前台的应用如果占用内存超过阈值的话也会被干掉(kill)。所以,解决 App 启动速度怎么做优化
,我们在写代码时,能注意到 App 内存使用情况,节省内存空间,减少不必要的内存创建,及时的释放内存等,都是对优化起到举足轻重的作用。
以上,就是冷启动和热启动
,希望大家能感受到我一直说的触类旁通
、融会贯通
的理念。
App的启动主要包括三个阶段
- main() 函数执行前
- main() 函数执行后
- 首屏渲染完成后
文章中说的内容,这里就不打算详细展开,简单的看本文的思维导图就可以,另外,文章中的很多细节的内容,在后续的篇章中会慢慢的介绍,这里就不展开,否则说不完事,大家感兴趣的,可以提前自行搜索,网络上真的都有了!本文需要提的是,解答一下前面说的几个有意思的问题
1、 +load() 方法和 +initialize() 方法
+load()
方法和 +initialize()
方法,大家都需要了解它们的区别和特性,这样才能更好的做性能优化。这里不作详细介绍,网络上能找到的,我这里不都不会说
,除非值得注意的内容。
2、 attribute((constructor)) 修饰的函数的调用
这个是C语言的函数属性,有2种类型:__attribute__((constructor))
和__attribute__((destructor))
1)函数属性功能
`__attribute__ ((constructor))`:会使函数在 `main()函数`之前执行
`__attribute__ ((destructor))`:会使函数在 `main()函数`之后执行
2)功能范围
函数属性`__attribute__((constructor))`和`__attribute__((destructor))`在可执行文件或者库文件里都可以生效
3)与全局变量比较
全局变量对象的构造函数和析构函数分别在`__attribute__((constructor))`和`__attribute__((destructor))`标志的函数之前调用。
4)PRIORITY 优先级
```
__attribute__((constructor(PRIORITY)))
__attribute__((destructor(PRIORITY)))
```
`__attribute__((constructor))` 按照优先级小到大执行,`__attribute__((destructor(PRIORITY)))` 则是从大到小执行。
注意:
1、可执行程序或库文件都可以使用此属性修饰函数
2、同一个可执行程序或库文件允许多个函数被修饰,执行顺序由代码编写顺序或编译链接顺序有关
引用来源:函数属性attribute((constructor))和attribute((destructor)) - tianmo2010的专栏
3、objc_msgSend 方法和 hook 内容
hook
的概率在很多的语言都有,因为安全和越狱等,针对 iOS 的 hook 网上也非常多,这里也不详细说了,后面的章节如果有相关安全的在说吧。相信大家网络上一定能找到很多资料!
4、怎样获取主线程调用栈?
相信有好奇心的同学,在阅读文章时,一定对怎样获取主线程调用栈的问题产生兴趣,但可能如果之前没有接触过,一定觉得太难了!根本找不到方向或者感觉!但是,你仔细想想,是不是真的这么难?没有方向?其实并不是,只要搜索一下,网络上也是一堆一堆的。当然,你想通过一篇文章就掌握所有这些相关的知识,那可能不太现实!你一定要明白,不劳而获永远是获得最少的!
,所以,还是要靠自己努力,另外,后续的章节还会有这方面的深入知识,到时候在解答吧。希望大家能利用自己的学习能力,习得不亦乐乎!
5、监控耗时和耗时统计
这个问题也值得大家注意,后续章节在一起讨论。
6、源码阅读
苹果公司已经开源了 Objective-C 的运行时代码。你可以在苹果公司的开源网站,找到 objc_msgSend的源码。
Facebook 开源了一个hook库,可以在 iOS 上运行的 Mach-O 二进制文件中动态地重新绑定符号,这个库叫 fishhook。
针对这种源码,大多数人一定说,我看不懂!我看不懂!我看不懂!
这个,与下面这个问题相似,一起来回答吧
7、C语言、汇编语言 看不懂?!
看不懂?看不懂?看不懂?
有没有发现,我们小时候也不懂中文,现在怎么就看懂了呢!学啊!学啊!学啊!
怎么学? 从入门
到放弃啊!怎么入门?
网络上有很多优秀的资源,大家如果真的感兴趣,一定要主动去了解,一味地抗拒永远不会得到结果和答案。汇编语言入门教程 - 阮一峰的网络日志 ,汇编语言入门学习就是这样简单,没有看不懂,只有不看懂!
人生苦短,我们努力吧~
8、其它问题
其它的还有很多问题,这里就不一一指出,比如 Swift 有 main 函数吗
?希望大家 多疑问,多思考,多总结!
,这样成长更快啦~
3、总结
回到本文的主题,“App 启动速度怎么做优化与监控?”,优化,不知道大家是否还记得之前的第一篇文章说到的,不记得的可以回去看看。监控的话,这里没有详细提到,因为性能监控
只是监控系统
的一小部分,后面的章节在细节展开吧。
这里先给出一个大纲,关于开发相关的工程优化,因为这也是我们从 《iOS开发高手课 - 极客时间》 来,我们要干什么?到那里去呢?
- 可以做什么?
- 工程优化:代码、规范、性能、AOP、日志
- 工程监控:耗时、内存、网络、卡顿、崩溃、瘦身、耗电
- 工程效率:响应式框架、函数式编程、APM、监控系统
- 技术深研:RN、Flutter、小程序、动态化
很多知识点,大家现在看到这篇文章感觉一气呵成,水到渠成的样子,但是其实是一点一点的思考和触想,可能有一个概念很久之前就有,但是怎么把这些知识串联一起,确实是需要非常深厚的功能,才能做到。所以,本次系列,我只能说尽量自己的力量,因为我相信不管是后来者,还是以后的我,都一定超越现在的我!
,所以,如果未来可以,可以在重写此系列,也是一件令人愉快的事!
注:更多关于 iOS 开发和程序开发相关的内容,可以查看此系列,目前还在连载中 【学习总结】iOS开发高手课 -- (连载中)| iHTCboy's blog,以上,希望对你有用!
参考
WWDC:
Article:
- iOS 在循环中使用计算属性导致内存暴涨 - 简书
- 可能碰到的iOS笔试面试题(6)--内存管理 - 简书
- iOS RunLoop详解 - 掘金
- dyld简介及加载过程分析 - 简书
- App启动之Dyld在做什么 - 掘金
- facebook/fishhook: A library that enables dynamically rebinding symbols in Mach-O binaries running on iOS.
- vsouza/awesome-ios: A curated list of awesome iOS ecosystem, including Objective-C and Swift Projects
- ming1016/GCDFetchFeed: “已阅”新版,RSS阅读器,使用FMDB做存储,ReactiveCocoa处理数据流向
- ming1016/SMCheckProject: 使用Swift3开发了个MacOS的程序可以检测出objc项目中无用方法,然后一键全部清理
- 汇编语言入门教程 - 阮一峰的网络日志
- UIApplicationMain函数 - 简书
- iOS启动时间优化 - 第七章
- How we cut our iOS app’s launch time in half (with this one cool trick)
- 深入理解iOS App的启动过程
- 如何精准度量iOSAPP启动时间
- 优化 App 的启动时间-杨萧玉
- iOS客户端启动速度优化-今日头条
- iOS App 启动性能优化-WiFi管家
- iOS App如何优化启动时间-Facebook
- 一次立竿见影的启动时间优化
- obj中国-Mach-O 可执行文件
- iOS app启动速度研究实践
- iOS App冷启动治理:来自美团外卖的实践
- iOS动态库的使用
- App启动之Dyld在做什么
- 获取任意线程调用栈的那些事 - KT的iOS开发小站
- 谈谈iOS获取调用链 - 掘金
- 函数属性attribute((constructor))和attribute((destructor)) - tianmo2010的专栏
- 真香!iOS云真机全新上线! - 腾讯WeTest
- iOS 云真机实现原理 · TesterHome
- 如何精确度量 iOS App 的启动时间 - 简书
- 如有侵权,联系必删!
- 如有不正确的地方,欢迎指导!
- 如有疑问,欢迎在评论区一起讨论!
注:本文首发于 iHTCboy's blog,如若转载,请注来源