美文网首页
启动优化尝试

启动优化尝试

作者: 大写的空气 | 来源:发表于2022-07-01 18:55 被阅读0次

基于公司项目的一次启动优化的尝试

一、启动时间统计
在Xcode13前,通过增加key能实现打印启动时间的功能,在Xcode13后,使用DYLD_PRINT_STATISTICS发现并不会打印启动时间。找了个替代方案

//
//  IMIAppLaunchTime.m
//  CMKit_Example
//
//  Created by Roffa Zhou on 2022/7/1.
//  Copyright © 2022 xxx. All rights reserved.
//

#import "IMIAppLaunchTime.h"

#import <sys/sysctl.h>

#import <mach/mach.h>


@implementation IMIAppLaunchTime


double __t1; // 创建进程时间 毫秒

double __t2; // before main

double __t3; // didfinsh

/// 获取进程创建时间
+ (CFAbsoluteTime)processStartTime {

    if (__t1 == 0) {

        struct kinfo_proc procInfo;

        NSProcessInfo *processInfo = [NSProcessInfo processInfo];
        int pid = [processInfo processIdentifier];

        int cmd[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};

        size_t size = sizeof(procInfo);

        if (sysctl(cmd, sizeof(cmd)/sizeof(*cmd), &procInfo, &size, NULL, 0) == 0) {

            __t1 = procInfo.kp_proc.p_un.__p_starttime.tv_sec * 1000.0 + procInfo.kp_proc.p_un.__p_starttime.tv_usec / 1000.0;

        }

    }

    return __t1;

}
/// 开始记录:在DidFinish中调用

+ (void)mark {

    double __t1 =  [IMIAppLaunchTime processStartTime];
    
    dispatch_async(dispatch_get_main_queue(), ^{ // 确保didFihish代码执行后调用

        if (__t3 == 0) {

            __t3 = CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970;

        }

        double pret = __t2 - __t1 / 1000;

        double didfinish = __t3 - __t2;

        double total = __t3 - __t1 / 1000;

        

        NSLog(@"----------App启动---------耗时:pre-main:%fs",pret);
        NSLog(@"----------App启动---------耗时:didfinish:%fs",didfinish);
        NSLog(@"----------App启动---------耗时:total:%fs",total);

    });
}

/// 构造方法在main调用前调用
/// 获取pre-main()阶段的结束时间点相对容易,可以直接取main()主函数的开始执行时间点.推荐使用__attribute__((constructor)) 构建器函数的被调用时间点作为pre-main()阶段结束时间点:__t2能最大程度实现解耦:

void static __attribute__((constructor)) before_main() {

    if (__t2 == 0) {

        __t2 = CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970;

    }

}

@end

计算load的时间是通过在Compile Sources中第一个文件增加load时间戳打印,再再main方法中增加时间戳打印,可能不准确,但是也能当一个load的运行时间作为判断了
NSLog(@"-------------App启动 main begin: %f", CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970);
经过统计得到各时间段如下,5次得到的结果(取5次中出现总耗时相对最稳定的一个值为参照基准,此次测试取总耗时1.8s为基准,与此值相差100ms以上的结果剔除)

描述 第一次 第二次 第三次 第四次 第五次 5次平均
load方法耗时 43ms 38ms 43ms 41ms 42ms 41ms
pre-main耗时 1.243s 1.213s 1.220s 1.238s 1.192s 1.295s
didfinish耗时 622ms 580ms 582ms 601ms 621ms 601ms
总耗时 1.865s 1.793s 1.802s 1.839s 1.813s 1.822s

综上,pre-main耗时较多,由于处理pre-main相对更为复杂,因此先从didfinish耗时开始进行优化


didFinish优化过程

  • 主线程异步执行可以暂缓执行的方法
//下面方法被移动到异步执行
dispatch_async(dispatch_get_main_queue(), ^{ // 确保didFihish代码执行后调用
        ILLogV(@"didFinishLaunching");

        //打印系统信息
        [self printSystemInfo];
        //设置显示样式
        [self initDisplayStyle];
        /// 设置APP更新本地存储
        [self setAppUpdateClickCancel];
        [self push_application:application didFinishLaunchingWithOptions:launchOptions];

    });

通过此次优化后,耗时结果如下

描述 第一次 第二次 第三次 第四次 第五次 5次平均
load方法耗时 43ms 38ms 43ms 41ms 42ms 41ms
pre-main耗时 1.275s 1.204s 1.199s 1.192s 1.205s 1.215s
didfinish耗时 588ms 604ms 596ms 594ms 585ms 593ms
总耗时 1.863s 1.809s 1.794s 1.786s 1.790s 1.808s

此次耗时统计对启动时间的优化不是特别明显,总耗时优化了1帧左右

  • 主线程异步创建首页相关视图、第三方sdk
    改造前
 [self initThirdSDKConfigWithApplication:application options:launchOptions];
 [self initManagerConfig];
 [self initWindows];          
 [self.window makeKeyAndVisible];
 [self initViews];

改造后

dispatch_async(dispatch_get_main_queue(), ^{ // 确保didFihish代码执行后调用
     //开始初始化
     [self initThirdSDKConfigWithApplication:application options:launchOptions];
     [self initManagerConfig];
     [self initViews];
 });
 [self initWindows];
UIViewController *launchVC = [[UIStoryboard storyboardWithName:@"LaunchScreen" bundle:nil] instantiateViewControllerWithIdentifier:@"launchScreen"];
self.window.rootViewController = launchVC;
[self.window makeKeyAndVisible];

由于视图采用异步绘制,会有瞬时的闪动,为了处理此问题,增加了读取启动图vc,默认先把启动图作为rootview

描述 第一次 第二次 第三次 第四次 第五次 5次平均
load方法耗时 43ms 38ms 43ms 41ms 42ms 41ms
pre-main耗时 1.312s 1.411s 1.258s 1.249s 1.368s 1.319s
didfinish耗时 259ms 271ms 286ms 258ms 285ms 272ms
总耗时 1.571s 1.682s 1.544s 1.507s 1.653s 1.591s

didfinish耗时从最初的601ms下降到272ms,优化了大概339ms,总耗时从1.822s下降到1.591s, 优化了大概231ms

相关文章

  • 启动优化尝试

    基于公司项目的一次启动优化的尝试 一、启动时间统计在Xcode13前,通过增加key能实现打印启动时间的功能,在X...

  • 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...

网友评论

      本文标题:启动优化尝试

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