包体积优化

716 阅读5分钟

分析

基于LinkMap分析iOS App各模块体积

获取linkmap文件

1.XCode开启编译选项Write Link Map File

XCode -> Project -> Build Settings -> 搜map -> 把Write Link Map File选项设为yes,并指定好linkMap的存储位置

2.编译后,到编译目录里找到该txt文件,文件名和路径就是上述的Path to Link Map File
位于~/Library/Developer/Xcode/DerivedData/XXX-eumsvrzbvgfofvbfsoqokmjprvuh/Build/Intermediates/XXX.build/Debug-iphoneos/XXX.build/

这个LinkMap里展示了整个可执行文件的全貌,列出了编译后的每一个.o目标文件的信息(包括静态链接库.a里的),以及每一个目标文件的代码段,数据段存储详情。

.a静态库大小分析:

1、lipo -info .a 可以查看是否包含v7架构

2.分离出不同架构的文件

lipo libTest.a -thin armv7 -output libTest_armv7.a

3、.分离出目标文件(.o)

ar -x libTest_armv7.a    

// 64同理

优化

资源优化

一、无用、重复资源删除

Unused和LSUnusedResources扫描冗余资源,后者相对效率高,但不支持命令行。

github.com/onevcat/Fen…

二、资源压缩

Asset.car中图片的优化

PNG图片压缩

ImageOptim无损压缩,ImageAlpha有损压缩。

音视频资源压缩

js/html文件打包压缩

三、资源动态下载

ODR按需加载

四、其他

资源替代:编程实现图片效果

使用iconfont替换icon和logo

设计统一规范及图片复用

资源优化.jpg

编译优化

可执行文件的优化

  • Linking

Dead Code Stripping:Yes  //链接时将无用代码去除

  • Deployment

Strip Linked Product:Yes  // 对最终二进制文件进行符号去除

  • Apple Clang - Code Generation

Optimization Level - Release:Fastest、Smallest[-Os]  //编译器优化级别

Symbols Hidden by Default - Release:Yes  //去掉不必要的调试符号  Link-Time Optimization

make strings read-only:YES  //复用字符串字面量

  • 重命名部分段绕过__TEXT段FirePlay加密

  • 多个可执行文件中存在多份相同代码

资源优化.jpg

代码优化

去掉未使用和重复的三方库

合并类似功能库

删除未使用库

选择更小的库

去掉未使用的代码

otool:分析删除无用类/方法的工具。

simian:重复代码扫描工具。

查找无用源代码方法:取project里所有源码文件列表,遍历所有代码找出import列表,找出没被import过的文件进行清理

查找无用静态库方法:ar命令列出静态库包含的.o文件,会在当前路径下列出所有的.o文件。对.a中的所有.o文件进行遍历,如果在可执行文件中没有命中该.o,则说明改.o文件为冗余文件。最后把所有的冗余文件按照大小进行排序即可。

3、减少冗余字符串,抽离长字符串保存为静态文件

iOS-LinkMapAnalyzer:解析LinkMap文件,分析各模块占用的包大小。(基于LinkMap完成,使用LinkMap文件对可执行文件安装包进行分析 3.3.1 Object files 3.3.2 Sections  3.3.3 Symbols)

\

\

\

重复代码整理 -基于插桩的行级别代码覆盖率:

长字符串抽离

代码混淆

减小文件大小。通过混淆类/方法名可以减小其长度。

-基于 Runtime 的轻量级运行时「类覆盖率」方案:

\

4、ARC->MRC

arc编译后会多出更多指令,一般更改后包size降8%左右。

\

\

\

\

其他高级优化:

How Uber Deals with Large iOS App Size

地址:eng.uber.com/how-uber-de…

\

根据 Uber 的统计,当 App 大小超过 AppStore 流量下载限制时,会导致应用程序安装减少 10%,注册减少 12%,首次预订减少 20%,从而导致收入损失。本文讲述 Uber 如何使用编译优化技术解决此问题,将 Uber App 的代码大小减少 23%,并使代码大小的增长率降低了 2 倍。

使用编译选项 -Osize 可以在模块内执行优化,编译器会通过 Function Outlining 来将重复代码片段重定向到单个实例实现压缩。但此优化对跨模块的代码则无能为力,这也将是本文的重点。

Uber 开发了自己的 iOS 构建流水线,新的流水线为每个模块生成 LLVM IR,而不是直接生成机器码。然后将所有 LLVM-IR 文件组合成一个大型 IR 文件并进行优化,再输入 llc 生成机器码。这确保了在识别候选重复片段时,会利用最大相似性,从而实现跨模块的优化。在模块内部,LLVM 在识别时采用的贪心思想也不能实现最优解,Uber 也通过多轮识别的方式进行了优化。

本文的很多方案已经提交到 LLVM。另外,一篇描述 论文 细节的论文也发表在了 "International Symposium on Code Generation and Optimization",感兴趣的同学可以阅读了解。

\

影响包大小的一些编码习惯和建议

Class Method vs C函数

Property vs IVAR

减少Block的使用

缩减方法参数 函数参数的个数

高频率使用的宏不要使用多行的方式

尽量避免代码的复制粘贴

\

参考链接

抖音品质建设 - iOS 安装包大小优化实践篇: mp.weixin.qq.com/s?__biz=MzI…

\

干货|今日头条iOS端安装包大小优化—思路与实践:mp.weixin.qq.com/s?__biz=MzI…

\

今日头条 iOS 安装包大小优化 - 新阶段、新实践:mp.weixin.qq.com/s?__biz=MzI…

\

今日头条优化实践: iOS 包大小二进制优化,一行代码减少 60 MB 下载大小:mp.weixin.qq.com/s?__biz=MzI…

\

一、包大小

参考高手课10:包大小:如何从资源和代码层面实现全方位瘦身? time.geekbang.org/column/arti…

\