美文网首页
启动优化

启动优化

作者: xxttw | 来源:发表于2023-06-26 19:09 被阅读0次
image.png
  • main函数之前都干了什么
    dyld: 动态链接器, 把所有可执行文件以及动态库递归的加载到内存中
    rebase/bindging: rebase是指调整镜像内部的指针, bindging是指绑定外部函数的指针
    objc setup Runtime初始化, 加载类和分类的信息,
    load & initialize & constructor: 调用所有类和分类的load方法, 初始化C和C++的静态常量,调用attribute((constructor))修饰的函数
    image.png
按照不同阶段的优化
  • dyld
    减少动态库, 合并一些动态库(定期清理不必要的动态库)
    减少Objc类, 分类的数量, 减少Selector数量(定期清理不必要的类和分类)
    减少c++虚函数数量
    Swift推荐使用struct

  • runtime
    使用+initialize方法和disphtch_once来代替_attribute(constructor), c++静态构造器, 类的+load方法, 因为这些方法启动的时候就会调用[';;;;;;;, 如果我们在里面做了一些额外的操作, 就会增加启动耗时,我们其实可以根据一些实际情况放到其他地方去

  • main
    在不影响用户体验的前提下, 尽可能的将一些操作延迟, 不要全部都放在didFinishLaunchingWithOption

rebase

每次应用启动时,我们获取到的地址都是变化的, 虚拟内存技术出现后, 就出现了ASLR(地址空间布局随机) 如下图:


image.png
image.png

修正偏移(rebase)
那么问题来了: 既然我们每次启动应用地址都是随机的, 我们如何找到真正存储某个函数的地址呢
Link Map File : 链接映射文件, 里面记录了每个类所生成的可执行文件的路径,CPU架构,目标文件,符号等信息
在buildSettings- 设置 Write Link Map File为YES,将 Link Map File(链接映射文件)写入到本地

image.png

我们可以根据应用启动的ASLR随机地址, 和Link Map File里的方法偏移量和修复这函数的真是内存地址,这个过程就是rebase


image.png

比如我们的ASLR地址为0x0000000102c88000 viewDidLoad方法的偏移量为0x100001C04
那么我们可以得出viewDidLoad函数的真实地址
rebase的结果如下图

image.png

从上面的结果来看,rebase之后的地址就是 -[ViewController viewDidLoad]的真是地址

符号绑定bindging

主要是针对外部函数的绑定, 指的是在运行时通过外部符号去找到真正的存放这个外部函数的地址

3.1.3 无用类清理

从前面的分析章节我们知道,不管是 rebase&bind 还是 Objc Init 阶段,工程中类及分类的代码量都会影响这几个阶段的耗时,尤其是大型 App 中不断发展的业务导致代码量巨多,而很多业务和代码在上线后并没有用到,所以对于这些无用代码的清理也能减少启动耗时。另外,无用代码清理对于包大小的收益更大,云音乐在包大小优化中做了无用代码的清理6

那么,如何才能找出哪些代码没有被用到呢?一般可以分为静态代码扫描和线上大数据统计两种方式。静态代码扫描还是从 MachO 出发, MachO 中的_objc_selrefs_objc_classrefs两个 section 中存储了引用到的 sel 和 class,而在__objc_classlistsection 中存储了所有的 sel 和 class,通过比较两者数据的差集就可以获取没有被用到的类。而我们知道 OC 是一门动态语言,所以很多类都是运行时调用,在删除类之前需要确保没有被真正地调用。线上大数据统计则采用类元数据中相应的标记为是否被初始化来统计。我们知道,在 OC 中,每个类都有自己的元数据,在元数据中的一个标记位存储着自己是否被初始化,这个标记位不受任何因素影响,只要有被初始化就会打标记,在 OC 的源码中获取标记位的方式如下:

struct objc_class : objc_object {
    bool isInitialized() {
        return getMeta()->data()->flags & RW_INITIALIZED;
    }
}
 - (BOOL)isUsedClass:(NSString *)cls { 
     Class metaCls = objc_getMetaClass(cls.UTF8String); 
     if (metaCls) { 
         uint64_t *bits = (__bridge void *)metaCls + 32; 
         uint32_t *data = (uint32_t *)(*bits & FAST_DATA_MASK); 
         if ((*data & RW_INITIALIZED) > 0) { 
             return YES; 
         } 
     } 
     return NO; 
 }
image.png

相关文章

  • App启动优化(三)启动优化方案

    系列文章 App启动优化(一)冷启动和热启动 App启动优化(二)启动时间测量 App启动优化(三)启动优化方案 ...

  • android启动优化

    感谢原作者涉及:应用启动流程启动优化(闪屏页优化、MultiDex 优化、WebView启动优化、启动耗时分析方法)

  • App优化,包括启动优化、界面卡顿优化,及监控方案

    启动优化 启动优化包括冷启动优化和热启动优化。 main之前 1.减少不必要的framework,因为动态链接比较...

  • 性能优化 - 启动时间

    应用的启动分为:冷启动,暖启动和热启动。其中冷启动是我们优化的重点,优化冷启动可能会同时优化暖启动和热启动。 冷启...

  • App白屏和启动优化的一些思路

    App启动优化 App启动优化原理与技术方案 启动优化 黑白屏问题 启动页面主题设置为图片 启动页面,不要再onC...

  • 冷启动优化

    App启动分为冷启动和热启动,我们说的启动优化一般是指冷启动优化。若要想优化,首先我们必须明确启动过程。 启动过程...

  • 【高级iOS】启动时间优化

    【高级iOS】启动时间优化 【高级iOS】启动时间优化

  • 冷启动优化

    冷启动优化主要优化两个方面 Application 性能优化 App启动页性能优化业务优化不在本章优化范围内。本章...

  • APP性能优化

    一、APP启动性能优化。 APP启动主要分冷启动和热启动,主要优化冷启动。 1.尽量减少didFinishLauc...

  • 性能优化

    一、启动优化 Activity启动形式分为三种类型:热启动、冷启动、温启动。重点在冷启动。 假优化:欺骗用户,去掉...

网友评论

      本文标题:启动优化

      本文链接:https://www.haomeiwen.com/subject/xdcicdtx.html