iOS的启动优化

news/2024/9/22 23:35:59/

应用的启动优化

当我们参与到大型应用的时候 会遇到一些启动时间过长的情况 这时候就需要使用到相关的操作。
总结来说,main()方法调用前,启动过程大体分为如下步骤:
先是LLVM把项目翻译成IR文件然后到backend

  1. LLVM clang

  2. pre-main

  3. main

  4. binding – 符号绑定

  5. rebase – 指针修复 (iOS14.3引进ASLR‘地址空间随机化’解决了虚拟内存从0开始的问题,物理内存地址随机 – 内存不够用’通过写入物理内存,使用时再从物理内存中读取‘ )

  6. MMU 内存管理单元 – 翻译地址 – page(页)

    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++类的构造函数)

·针对APP启动时间的优化还是很有必要的。

   关于APP启动时间的分析和优化可以以main()为分界点,分为main()方法执行之前的加载时间(pre-main time)和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:因为iOS13之后就失效了,这两个属性所以使用时需要使用一个iOS13以下的模拟器)

如果你想打印dyld装载动态库的顺序,可以设置这个环境变量 DYLD_PRINT_LIBRARIES。
图:
在这里插入图片描述
在这里插入图片描述

请添加图片描述

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)。

优化动作

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

2、合并动态库。

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

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

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

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

查找项目中没有用到的类

下载工具fui ,link:https://github.com/dblock/fui

下载安装好工具以后
cd到工程目录下运行,$fui find ,然后就会打印出没有被使用的class

如何查找到没有被调用的函数

python FindSelectorsUnrefs.py -a {这里是工程中.app文件的地址在finder找到直接拖过来}

对应脚本FindSelectorsUnrefs.py可以在我上传的资源里面查找。

找到项目中没有被使用的图片资源

在我上传的资源文件中找到LSUnusedResources,的Mac应用跑起来然后把工程拖进去就可以了。

二进制重排

通过创建.order 文件 与项目进行绑定,使APP启动的时候能够按照我们制定的内容把我们需要的符号排在前面, 减少我们的程序启动过程中page fault的次数,从而减少启动时间。至于怎么才能知道要优化正确的顺训呢这时候需要clang 插桩

clang插桩


http://www.ppmy.cn/news/5233.html

相关文章

基础背包问题--0 1背包与完全背包

🎉🎉🎉写在前面: 博主主页:🌹🌹🌹戳一戳,欢迎大佬指点! 目标梦想:进大厂,立志成为一个牛掰的Java程序猿,虽然现在还是一个…

Nature Communications:人类丘脑的基因结构及其与十种常见大脑疾病的重叠

丘脑是位于大脑中心的重要交流中枢,由不同的核组成,对意识和高级皮层功能至关重要。丘脑结构和功能的改变涉及到常见的大脑疾病的发病机制,但丘脑的遗传结构仍然很大程度上未知。在这里,使用来自30114个个体的大脑扫描和基因型数据…

Fabric.js 修改画布交互方式到底有什么用?

本文简介 点赞 关注 收藏 学会了 fabric.js 为我们提供了很多厉害的方法。今天要搞明白的一个东西是 canvas.interactive 。 官方文档对 canvas.interactive 的解释是: Indicates that canvas is interactive. This property should not be changed. canvas.in…

LeetCode 321 周赛

2485. 找出中枢整数 给你一个正整数 n ,找出满足下述条件的 中枢整数 x : 1 和 x 之间的所有元素之和等于 x 和 n 之间所有元素之和。 返回中枢整数 x 。如果不存在中枢整数,则返回 -1 。题目保证对于给定的输入,至多存在一个中…

2022卡塔尔世界杯 | 我与足球的爱恨情仇

超燃世界杯,决战卡塔尔⚽我与足球在生活上的交集一、小学二、中学三、大学💻我与足球在技术上的碰撞一、与足球有关的题目训练二、使用Java代码做一个足球小游戏🏆2022卡塔尔世界杯冠军 —— 阿根廷yyds一、球队比赛过程二、热门球员介绍三、…

HTTP报文详解

个人博客地址: http://xiaohe-blog.top/ 文章目录1. 请求1.1 请求行1.2 请求头1.3 空白行1.4 请求体2. 响应2.1 状态行2.2 响应头2.3 空白行2.4 响应体2.5 HTTP报文总结3. HTTP方法4. GET与POST的区别5. 状态码1. 请求 1.1 请求行 请求方式 请求地址 请求协议版本号…

第03讲:Redis的持久化方案

前言 redis是一个内存数据库,当redis服务器重启,获取电脑重启,数据会丢失,我们可以将redis内存中的数据持久化保存到硬盘的文件中。 redis提供两种持久化方式: RDB:快照,通过从服务器保存和持久化AOF&…

深度学习Week11-调用官方权重进行检测(YOLOv5)

前言: 很早之前,我发过小白YOLOv5全流程-训练实现数字识别_牛大了2022的博客-CSDN博客_yolov5数字识别这篇文章,里面用简练语言分享用yolov5训练自己的识别器,但包括我在内许多人仍不了解其运行原理;过去两周&#xff…