当前位置: 首页 > 科技观察

iOS启动优化之二进制重排

时间:2023-03-12 06:38:18 科技观察

随着iOS项目越来越大,启动时间会越来越慢。如何优化APP的启动时间,让用户有更好的体验??应用程序启动介绍应用程序启动分为冷启动和热启动。我们杀死应用程序,然后立即启动它。此时内存中与应用程序相关的数据并不会立即被清除,所以此时的启动不是冷启动;热启动是指内存中还有应用程序相关的数据,应用程序运行所需的数据不需要完全从硬盘加载到内存中。监控启动时间我们可以通过设置环境变量来监控应用程序的启动时间。环境变量设置请参考Xcode环境变量。我们设置环境变量DYLD_PRINT_STATISTICS,运行项目,在应用启动时打印耗时:printout应用启动时间如下:我们以main函数为分离点,将启动时间优化到main函数之前在主要功能之后。这里打印的pre-main时间是main函数之前的时间。dylibloadingtime:加载动态库耗时。苹果建议项目中自定义动态库不要超过6个动态库。如果动态库超过6个,就要考虑动态库合并;rebase/binding时间:偏移校正(rebase)和符号绑定(binding);offsetcorrection是一种安全机制——ASLR,原理是产生一个随机值,加在申请内存地址的前面,达到方法和函数地址随机化的目的,解决安全问题。所有方法、函数和数据的内存地址都会把这个随机值加到原来的真实地址上,每次启动随机值都不一样,这样别人就无法得到方法、函数或数据的真实地址;符号绑定是指方法名和方法实现,即sel和IMP的绑定。ObjCsetuptime:Object-C类注册耗时;没有权威统计,每增加20000个类,这个时间就会增加800ms;减少类的数量可以减少启动时间;initializertime:耗时的加载方法和构造方法。所以在项目中,需要尽量减少对加载方法的重写,将加载方法的操作放在初始化中。以上是主要功能前启动时间及相关优化方案的说明;对于main函数之后的启动时间,我们可以通过代码比如在main函数中记录一个时间,在第一个界面显示的viewDidLoad方法中记录一个时间。两个时间的区别是main函数之后的启动时间。因为main函数之后的消费有时候需要根据不同的项目来区分,不能一概而论。这里有几个减少数据加载的优化建议。最好使用延迟加载,比如加载第三个库;删除项目中不再使用的类和方法;采用多线程技术加载数据,充分利用CPU资源;启动时的界面不要使用storyboard或者xib,尽量使用纯代码,因为storyboard或者xib有一步代码转换操作,同样比较耗时。二进制重排技术背景应用程序在运行时,采用虚拟内存和物理内存相结合的方式加载数据;虚拟内存采用分页方式进行管理,当使用到虚拟内存某一页的数据时,对应的将真实数据加载到物理内存中,并形成虚拟内存和物理内存之间的映射关系。此操作称为页面错误,并且此操作很耗时。查看iOS应用加载数据的顺序,我们可以通过将WriteLinkMapFile设置为yes来查看应用数据加载的顺序。clean工程,然后command+B编译工程,进入Products的xx.app目录然后进入下面的目录,找到下面的文件,打开这个文件Demo-LinkMap-normal-x86_64.txt命令在这里是应用程序数据加载的顺序,这里的顺序是由以下两个因素决定的按文件顺序从上到下文件中方法的顺序是从上到下。验证文件的顺序是否为实际加载顺序。您可以修改文件或方法的顺序,然后重新编译以检查链接映射文件中方法的顺序是否已更改。二进制重排方案由于我们在应用程序启动时可能只需要某些文件中的某些方法,根据实际的方法加载顺序,由于页面错误的存在,应用程序启动时需要加载大量用户。丢失的数据造成了大量的时间消耗。为此,我们只需要在应用程序启动时只加载启动时需要的方法即可。事实上,数据可以稍后加载;为此,我们可以创建一个.order文件来修改方法或函数的加载顺序。打开hank.order文件,查看以下方法的顺序,将此文件配置到对应的xcode工程中,清理干净,然后重新编译,查看Demo-LinkMap-normal-x86_64文件。这样,我们就成功修改了方法或者函数的加载顺序,那么我们只需要知道应用程序启动时执行了哪些方法,将它们排序,放到.order文件中,就可以只加载什么了我们需要在应用程序启动时提供数据,减少缺页次数,从而减少启动时间。