iOS 性能优化三

作者: 飞不越疯人院 | 来源:发表于2020-08-21 11:38 被阅读0次

    主要讲解APP冷启动的优化

    iOS 性能优化一
    iOS 性能优化二
    iOS 性能优化三


    1. APP 启动的分类

    冷启动: 从零开始, 点击 APP加载;
    热启动: APP 已经在内存中, 再次点击图标后加载;
    我们常说的APP启动优化主要是针对冷启动;
    通过在xcode 中添加环境变量可以打印出启动的时间;
    Edit scheme -> Run -> Environment Variables 添加DYLD_PRINT_STATISTICS 值为1
    启动后就会打印启动信息;
    执行main函数之前的时间:

    Total pre-main time: 567.86 milliseconds (100.0%)
             dylib loading time: 153.19 milliseconds (26.9%)
            rebase/binding time: 229.51 milliseconds (40.4%)
                ObjC setup time: 135.73 milliseconds (23.9%)
               initializer time:  49.28 milliseconds (8.6%)
               slowest intializers :
                 libSystem.B.dylib :   6.81 milliseconds (1.1%)
        libMainThreadChecker.dylib :  29.43 milliseconds (5.1%)
    

    DYLD_PRINT_STATISTICS改为DYLD_PRINT_STATISTICS_DETAILS可以打印更加详细的信息;

    2. APP 冷启动经历哪些阶段

    点击 APP 图标到加载成功经历大概三个阶段;

      1. dyld(dynamic link editor)阶段: APP的动态链接器, 用来装载 Mach-O 文件(可执行文件, 动态库等);
        1.1 装载APP的可执行文件, 同时递归加载所有的依赖动态库;
        1.2 当可执行文件和动态库都加载完成后, 通知runtime进行下一步操作;
      1. runtime阶段, 请先看下runtime源码中的ojbc_init函数;
        2.1 调用map_image对可执行文件内容解析;
        2.2 调用load_images调用所有ClassCategory的的+load方法
        2.3 各种objc结构的初始化(注册类, 初始化类对象等);
        2.4 至此可执行文件和动态库中的信息(class, protocol, SEL, IMP)已经按照格式加载到了内存中, 通过runtime管理;接下来调用main函数;
      1. main函数阶段;
        3.1 调用UIApplicationMain函数
        3.2 调用Appdelegateapplication:()didFinishLaunchingWithOptions()函数;

    3. 优化启动时间

    针对上面的分析APP启动过程中做了那些操作, 可以优化APP的启动时间

      1. dyld阶段:
        1.1 减少不必要的动态库, 合并一些库;
        1.2 减少objc的类, 分类, 方法的数量;
        1.3 swift能用struct的地方就不要创建类;
      1. runtime 阶段:
        尽量不要在+load方法中写逻辑,使用+initialize+ dispatch_once方式替代;
      1. main阶段:
        3.1 不要将所有的操作都放在didFinishLaunchingWithOptions中加载, 将一些不影响用户体验的操作延迟加载;
        3.2 按需加载; 多个tab时, 尽量只加载当前 tab 的内容;

    补充

    1. runtime 入口的objc_init方法
    /***********************************************************************
    * _objc_init
    * Bootstrap initialization. Registers our image notifier with dyld.
    * Called by libSystem BEFORE library initialization time
    **********************************************************************/
    
    void _objc_init(void)
    {
        static bool initialized = false;
        if (initialized) return;
        initialized = true;
        
        // fixme defer initialization until an objc-using image is found?
        environ_init();
        tls_init();
        static_init();
        runtime_init();
        exception_init();
        cache_init();
        _imp_implementationWithBlock_init();
        _dyld_objc_notify_register(&map_images, load_images, unmap_image);
    #if __OBJC2__
        didCallDyldNotifyRegister = true;
    #endif
    }
    

    相关文章

      网友评论

        本文标题:iOS 性能优化三

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