美文网首页
2021-09-07

2021-09-07

作者: kangomake | 来源:发表于2021-09-07 16:39 被阅读0次

    以下内容引用

    1.应用程序启动过程,启动优化
    - 应用启动时是用怎样加载所有依赖的Mach-O文件的?
    - 请列举你所知道main()函数之前耗时的因素都有哪些
    
    App启动分为两种:
    - 冷启动(Cold Launch):从零开始启动app
    - 热启动(Warm Launch):app已在内存中,在后台存活,再次点击图标启动app
    
    启动时间的优化,主要是针对冷启动进行优化
    1、通过添加环境变量可以打印app的启动时间分析(详情请见下图)
    - DYLD_PRINT_STATISTICS
    - DYLD_PRINT_STATISTICS_DETAILS(比上一个详细)
    - 一般400毫秒以内正常
    
    打印结果:
    Total pre-main time: 238.05 milliseconds (100.0%)              // main函数调用之前(pre-main)总耗时
             dylib loading time: 249.65 milliseconds (104.8%)      // 动态库耗时 
            rebase/binding time: 126687488.8 seconds (18128259.6%) 
                ObjC setup time:  10.67 milliseconds (4.4%)        // OC结构体准备耗时 
               initializer time:  52.83 milliseconds (22.1%)       // 初始化耗时 
               slowest intializers :                               // 比较慢的加载 
                 libSystem.B.dylib :   6.63 milliseconds (2.7%)
       libBacktraceRecording.dylib :   6.61 milliseconds (2.7%)
        libMainThreadChecker.dylib :  31.82 milliseconds (13.3%)
    
    2、冷启动可以概括为3大阶段
    - dyld
    - runtime
    - main
    
    3、dyld(dynamic link editor),Apple的动态连接器,可以装载Mach-O(可执行文件、动态库等)
    - 装载app的可执行文件,同时递归加载所有依赖的动态库
    - 当dyld把可执行文件、动态库都装载完成后,会通知runtime进行下一步处理
    
    4、runtime所做的事情
    - 调用map_images函数中调用call_load_methods,调用所有Class和Category的+load方法
    - 进行各种objc结构的初始化(注册objc类、初始化类对象等等)
    - 调用C++静态初始化器和__attribure__((constructor))修饰的函数(JSONKit中存在具体应用)
    - 到此为止,可执行文件和动态库中所有的符号(Class, Protocol, Selector, IMP...)都已按格式成功加载到内存中,被runtime所管理
    
    5、总结
    - app的启动由dylb主导,将可执行文件加载到内存,顺便加载所有依赖的动态库
    - 并由runtime负责加载成objc定义的结构
    - 所有初始化工作结束后,dyld就会调用main函数
    - 接下来就是ApplicationMain函数,AppDelegate的application:didFinishLaunchingWithOptions:方法
    
    6、按照不同的阶段优化
    dyld
    - 减少动态库、合并一些动态库(定期清理不必要的动态库)
    - 减少objc类、分类的数量、减少selector数量(定期清理不必要的类、分类)
    - 减少C++虚构函数
    - Swift尽量使用struct
    
    runtime
    - 使用+initialize方法和dispatch_once取代所有的__attribute__((constructor))、C++静态构造器、Objc的+load方法
    
    main
    - 在不影响用户体验的前提下,尽可能将一些操作延迟,不要全部都放在finishLaunching方法中
    - 按需加载
    
    image.png
    2.包体积优化
    安装包瘦身(ipa):资源文件、可执行文件
    
    资源文件(图片、音频、视频等)
    - 采取无损压缩(使用工具)
    - 去除没有用到的资源(https://github.com/tinymind/LSUnusedResources)
    
    可执行文件瘦身:
    - 编译器优化(Xcode相关配置)
    - 利用AppCode(https://www.jetbrains.com/objc/)检测未使用的代码:菜单栏 -> Code -> Inspect Code
    - 生成LinkMap,可以查看可执行文件的具体组成
    - 可借助第三方工具解析LinkMap文件:http://github.com/huanxsd/LinkMap
    
    
    3.项目的优化、性能优化

    你一般是如何优化你的APP的

    启动速度:
    - 启动过程中做的事情越少越好(尽可能将多个接口合并)
    - 不在UI线程上作耗时的操作(数据的处理在子线程进行,处理完通知主线程刷新节目)
    - 在合适的时机开始后台任务(例如在用户指引节目就可以开始准备加载的数据)
    - 尽量减小包的大小
    - 辅助工具(友盟,听云,Flurry)
    
    页面浏览速度
    - json的处理(iOS 自带的NSJSONSerialization,Jsonkit,SBJson)
    - 数据的分页(后端数据多的话,就要分页返回,例如网易新闻,或者 微博记录)
    - 数据压缩(大数据也可以压缩返回,减少流量,加快反应速度)
    - 内容缓存(例如网易新闻的最新新闻列表都是要缓存到本地,从本地加载,可以缓存到内存,或者数据库,根据情况而定)
    - 延时加载tab(比如app有5个tab,可以先加载第一个要显示的tab,其他的在显示时候加载,按需加载
    - 算法的优化(核心算法的优化,例如有些app 有个 联系人姓名用汉语拼音的首字母排序)
    
    操作流畅度优化
    - Tableview 优化(tableview cell的加载优化)
    - ViewController加载优化(不同view之间的跳转,可以提前准备好数据)
    
    
    4.静态库、动态库相关

    iOS 库.a 和 framework的区别和创建

    1、什么是库?
    - 共享代码,实现代码的复用,一般分为静态库和动态库。
    
    2、静态库和动态库的区别
    静态库(.a和.framework 样式):
    - 链接时完整的拷贝到可执行文件,多次使用多次拷贝,造成冗余,使包变的更大
    - 但是代码装载速度快,执行速度略比动态库快
    
    动态库:(.dylib和.framework)
    - 链接时不复制,程序运行时由系统加在到内存中,供系统调用,系统加在一次,多次使用,共用节省内存。
    
    3、为什么framework既是静态又是动态?
    - 系统的framework是动态的,自己创建的是静态的。
    
    4、.a 和 .framework 的区别是什么?
    - .a 是单纯的二进制文件,需要 .h文件配合,不能直接使用
    - .framework是二进制文件+资源文件,可以直接使用。 .framework = .a + .h + sorrceFile(资源文件)
    
    

    相关文章

      网友评论

          本文标题:2021-09-07

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