Mach-O 文件构成:
- Header 头部:指明了 CPU 架构,文件类型,
LoadCommand
的个数,用来校验Mach-O
合法性和定位文件的运行环境 LoadCommand
加载命令:告诉 OS 如何加载和链接段数据 segmentData
数据段:存放 __DATA(数据段) 和 __Text(代码段) 段的数据,真正存储 App 二进制数据的地方,
如何检测无用代码?
-
静态检测:用 otool 工具分析
Mach-O
文件,针对classlist
段(所有的OC 类和 Swift 类)和classrefs
(所有引用类)做差集,就能找到未使用的类。除了这两个主要的,还有一些其他情况,比如:- 通过字符串调用的类、
__DATA__cfstring
- 没有直接调用这个类,但是这个类的
+load
调用了 检测__DATA __objc_nlclslist
段()
- 通过字符串调用的类、
-
动态检测:通过检测 OC 类的元数据中某一个标记位
RW_INITIALIZED
,就能找出所有使用到的类,再跟类的全集做差集,就能得到未使用的类了。参考WWDC:Advancements in the Objective-C runtime
如何配置编译选项
-
符号剥离(链接期的优化):官方文档
App 本身可以看做是一个大的「动态库」,既然是「动态库」那么就会有向外暴露的符号(也就是 Exported Symbols),这些符号实际上是没有用的。可以想办法删掉。(方法是在项目的 Build setting 中,设置
EXPORTED_SYMBOLS_FILE
为一个路径,路径指向一个 txt 文件,在 txt 文件里写了哪个符号,那么这个符号就会被保留,其他符号就会被裁剪掉) -
GCC 编译优化:
GCC_OPTIMIZATION_LEVEL
更激进的 GCC 编译优化—— Oz 模式,原理是通过更多的外联来降低函数的内联层级,但是同时函数的调用栈就会变深,等于是用时间增加换了空间减少,函数的执行效率被降低。
如何处理资源文件?
-
用 python 脚本扫描出扫描出项目中所有用到的图片,用 LSUnusedResources 扫描出所有项目内未使用的图片资源,做一个去重,剩下的就是实际上未使用的图片。删除无用图片。
-
有损压缩,将所有图片资源都做一次有损压缩。tinypng
-
用 AssetCatelog 管理。
- 有两个好处,一个是 app thinning,Apple 会把不同分辨率的 资源包下发给不同的设备,所以整体的 IPA 包虽然变大了,但是实际下载的安装大小是变小的
- Xcode 会对 AssetCatelog 里的图片做一个无损压缩,然后把多张图合并成一张大图,读取的时候只能通过 Apple 的 API,它通过坐标等方式,从合成后的大图中获取对应的图片。这种方式对小图有更好的效果。
如何防劣化?
- 每次打包后触发包检测脚本,生成当前包的体积分析报告,让其他开发者和产品有感知
- 定期代码检测,下线无用代码
- 合并代码时,如果有新增图片资源的,确保要先经过有损压缩