重学OC第二十四篇:启动优化

本文介绍了iOS应用的冷启动优化,包括性能检测、官方建议的启动时间要求以及优化策略。重点讲解了二进制重排的原理,如PageFault检测、通过.order文件进行重排,并提供了Clang插桩的使用步骤,以减少启动时的硬盘到内存操作次数,提升应用启动速度。
摘要由CSDN通过智能技术生成

前言

启动分为冷启动和热启动,主要区别是内存是否有APP加载的数据,如果所有的数据需从硬盘读取后加载到内存,那就为冷启动。下面主要是关于冷启动方面的优化。

一、冷启动

1.1 性能检测

APP启动分两个阶段来测试:

  • main函数前(pre-main)
    主要是dyld流程部分,包括动态库加载、类的加载、C++静态对象处理等。通过在Xcode中添加环境变量DYLD_PRINT_STATISTICS为YES
    在这里插入图片描述
//模拟器数据不真实,仅参考
Total pre-main time: 126687488.8 seconds (0.0%)   //总耗时
	dylib loading time: 258.93 milliseconds (0.0%) //dyld加载耗时,官方建议自定义动态库不超过6个
	rebase/binding time: 126687487.6 seconds (0.0%)//重定址和符号绑定耗时
   	ObjC setup time: 632.00 milliseconds (0.0%)//OC类注册耗时
   	initializer time: 366.95 milliseconds (0.0%)//+load、c++构造初始化耗时
   	slowest intializers :  //最慢的初始化器
  • main函数后
    从main()函数开始至applicationWillFinishLaunching结束,我们统一称为main()函数之后的部分。利用锚点分析applicationWillFinishLaunching的耗时。

1.2 优化

官方建议的启动时间要求:

  • 应该在400ms内完成main()函数之前的加载
  • 整体过程耗时不能超过20秒,否则系统会kill掉进程,App启动失败

对于main函数前的优化

  • 减少OC类,移除不需要的类
  • 减少动态库,移除不需要的动态库。可通过动态库合并来让动态库数量不超过6个
  • 尽量不要写__attribute__((constructor))的C函数,也尽量不要用到C++的静态对象
  • 尽量不要使用+load
  • 压缩图片大小,减少I/O操作量

对于main函数后的优化

  • 延迟不必要的页面、配置等加载
  • 耗时操作考虑多线程异步操作
  • 使用二进制重排来减少启动时硬盘到内存的操作次数。

二、二进制重排

二进制重排指的是重排编译阶段的代码文件和函数的顺序。要了解二进制重排需了解虚拟内存,相关知识可参考《深入理解计算机系统》第9章虚拟内存中的内容。

2.1 原理

编译器生成二进制代码时,默认按照链接的.o顺序写文件,按照.o内部顺序写函数,如果函数跨页了,就会触发多次Page Fault,所以把函数排到一个Page里,只需要一次Page Fault。
iOS中页的大小可通过下面代码打印

extern vm_size_t vm_page_size;
NSLog(@"%lx", vm_page_size);

在真机中每页为16KB,模拟器中为4KB。

2.1.1 PageFault检测

通过Instruments中的Systme Trace,选择项目,选中main thread,选择Virtual Memory,查看File Backed Page In(PageFault)和其他的相关次数、时间等。

2.2 重排

要进行重排要看到二进制数据的顺序,如何进行重排。

2.2.1 二进制符号顺序查看

Build Settings中搜索link Map,设置Write Link Map File为YES,然后编译,在文件中向上两级找到Intermediates.noindex,进入xxx.build最后找到xxx-LinkMap-normal-x86_64.txt文件,打开找到Symbol可看到按编译时文件和文件内部函数书写顺序排列。

2.2.2 通过.order文件重排

创建xxx.order文件,在Build Settings中搜索order file,加入./xxx.order,然后编译。
那xxx.order文件中的内容怎么来,可通过clang插桩hook函数然后保存到xxx.order中。

2.2.3 Clang插桩

官方介绍: https://clang.llvm.org/docs/SanitizerCoverage.html#tracing-pcs

SanitizerCoverage 是 Clang 内置的一个代码覆盖工具,它把一系列以 _sanitizer_cov_trace_pc 为前缀的函数调用插入到用户定义的函数里来实现全局 AOP。其覆盖之广,包含 Swift/Objective-C/C/C++ 等语言,Method/Function/Block 全支持。

使用步骤:

  1. Build Settings 搜索 Other C Flags,添加-fsanitize-coverage=func, trace-pc-guard参数(OC); Other Swift Flags添加-sanitize-coverage=func 和 -sanitize=undefined(swift)
  2. 在__sanitizer_cov_trace_pc_guard_init和__sanitizer_cov_trace_pc_guard_init方法中进行相关代码编写或直接使用第三方AppOrderFiles
  3. 在didFinishLaunchingWithOptions中调用相应的方法生成xxx.order文件并进行调用顺序重排<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值