6

🐻记录启动速度优化30%的过程

 3 years ago
source link: https://juejin.cn/post/6844904151483154445
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
2020年05月08日 阅读 1161

🐻记录启动速度优化30%的过程

我曾在掘金上发布过一个沸点,关于使用use_frameworks! :linkage => :static的困惑,也在技术群里询问过、同时问了一些小伙伴,不过没能获得自己想要的答案。我为此查阅了很多资料,总算是能解释通了。

包变小的原因:www.jianshu.com/p/03aac1412…

优化App的启动速度时,阅读了很多优秀的文章,同时也发现有些文章表述有问题,甚至会影响开发者的思维,带入一个误区,比如静态库、动态库的这个概念,因此,总结下,以免读者百思不得其解。利用Cocoapods新特性提高30%的启动速度,见本文最后。

  • 我们自己的Framework 都是 伪Framework,只有官方的是 真Framework

  • 通过Pod引入的Framework可以是静态的,也可以是动态的。和设置有关,你可以手动更改,在Build Settings => Mach-O Type 改为 Static Library:那么就是静态的了,默认是Dynamic。

  • 如果这个库不是App 和 Extension共享的,那么请尽可能的使用静态库,这样不仅会加快启动速度,还会优化包大小。

Extension 和 App 是两个分开的可执行文件,同时需要共享代码,这种情况下动态库的支持就是必不可少的了。但是这种动态 Framework 和系统的 UIKit.Framework 还是有很大区别。系统的 Framework 不需要拷贝到目标程序中,我们自己做出来的 Framework 哪怕是动态的,最后也还是要拷贝到 App 中(App 和 Extension 的 Bundle 是共享的),因此苹果又把这种 Framework 称为 Embedded Framework。

动态库与静态库区别

什么是库,库(Library)说白了就是一段编译好的二进制代码,加上头文件就可以供别人使用。

什么时候我们会用到库呢?一种情况是某些代码需要给别人使用,但是我们不希望别人看到源码,就需要以库的形式进行封装,只暴露出头文件。另外一种情况是,对于某些不会进行大的改动的代码,我们想减少编译的时间,就可以把它打包成库,因为库是已经编译好的二进制了,编译的时候只需要 Link 一下,不会浪费编译时间。

上面提到库在使用的时候需要 Link,Link 的方式有两种,静态和动态,于是便产生了静态库和动态库。

原文:segmentfault.com/a/119000000… ---- 作者:skyline75489

Swift 不利因素

Swift 虽然在 5.0 版本完成了 ABI 稳定,但是在低版本操作系统中 (iOS 12.2 以下) 仍旧会有一些不够完美的地方。

在低于 iOS12.2 以下的操作系统会带来相应的包大小增加负担,因为Swift1.x,2.x,3.x,API不稳定,很多东西没办法放到系统更新安装包中,只能把Swift运行时打包进自己的App中,因此会增大一部分。

假如你的手机系统是ios10,假如把当时最新的Swift2.x的运行库放到系统中,过了几个月swift3.x出来了,有人用swift3.x写了个软件,你去安装它,由于别人是swift3.x,但你只有Swift2.x的运行库,那怎么办,所以苹果被逼无奈,只能报把运行支持库打包到app中,因此,理论上会有这部分的增加。

在低于 iOS12.2 以下的操作系统会有 100-200ms不等的启动耗时增加,因为使用的是动态库,运行时链接。

摘抄:mp.weixin.qq.com/s/oHGkoGzhM…

利用Cocoapods1.9新特性提高30%的启动速度,包大小减少10MB

在Podfile将use_frameworks!修改为:

use_frameworks! :linkage => :static
复制代码

可以提高30%的启动速度,包大小减少10MB(与使用的动态库数量与类型有关)。

CocoaPods 1.9 Beta已经到来!

即刻团队早期的文章可验证

动态库你自己的,共享给谁用?莫非你的Alamofire还能共享给其他app?显然动态库有点浪费,不如静态库实在,能用静态库就用静态库,除非。。。

我问了好多人:大家都说改成静态库,包大小会加大,我之前也深信不疑,直到我发现无法解释时,才追根溯源。

如果你有不同观点。评论区留言。或入群battle。

二进制重排

第一步:安装 AppOrderFiles(使用pod)

post_install do |installer|
    installer.pods_project.targets.each do |target|
        target.build_configurations.each do |config|
            config.build_settings['ARCHS'] = 'arm64'
            config.build_settings['OTHER_CFLAGS'] = '-fsanitize-coverage=func,trace-pc-guard'
            config.build_settings['OTHER_SWIFT_FLAGS'] = '-sanitize-coverage=func -sanitize=undefined'
        end
    end
end
复制代码

第二步:增加Flags

Other C Flags 中增加 -fsanitize-coverage=func,trace-pc-guard Other Swift Flags 中增加 -sanitize-coverage=func 与 -sanitize=undefined

第三步:在viewdidAppera中增加(首屏渲染结束后)

AppOrderFiles { (path) in XHPrint("quinn---- (path)") }

运行App,获取到函数调用顺序的文件。path 表示路径

第四步:在 xcode中搜索 order file 增加配置,把第三步生成的文件,拷贝到工程中,并引用

第五步,删除 AppOrderFiles以及先关代码,进行测试。

AppOrderFiles 利用 Clang SanitizerCoverage

简单来说 SanitizerCoverage 是 Clang 内置的一个代码覆盖工具。它把一系列以 _sanitizer_cov_trace_pc 为前缀的函数调用插入到用户定义的函数里,借此实现了全局 AOP 的大杀器。其覆盖之广,包含 Swift/Objective-C/C/C++ 等语言,Method/Function/Block 全支持。

开启 SanitizerCoverage 的方法是:在 build settings 里的 “Other C Flags” 中添加 -fsanitize-coverage=func,trace-pc-guard。如果含有 Swift 代码的话,还需要在 “Other Swift Flags” 中加入 -sanitize-coverage=func 和 -sanitize=undefined。所有链接到 App 中的二进制都需要开启 SanitizerCoverage,这样才能完全覆盖到所有调用。

地址:github.com/yulingtianx…


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK