iOS ipa包瘦身

APP 的大小是分为 APP 下载大小和安装大小两个概念的。

  • 下载大小是指 App 压缩包(也就是 .ipa 文件)所占的空间,用户在下载 App 时,下载的是压缩包,这样做可以节省流量;
  • 当压缩包下载完成后,就会自动解压,解压过程也就是通常所说的安装过程;安装大小就是指压缩包解压后所占用的空间。

用户在App Store看到的大小是安装大小。如果想看安装包在各机型上的下载、安装大小可以在 App Store Connect 后台查看。

App Store OTA 下载大小限制:

虽然苹果历年都会调整 App 下载大小,由之前的 100M 到后来的 150M 再到现在的 200M。如今,App 下载大小超出 200 MB 时 ,会出现两种情况:

  • iOS 13 以下的用户,无法通过蜂窝数据下载 App;
  • iOS 13 及以上的用户,需要手动设置才可以使用蜂窝网络下载 App。

图片减包

相比起代码(5kb/千行)的平均占用来说,对图片进行减包是API包瘦身的最直接、最高效的手段

对图片资源的处理方式包括四种

  1. 通过请求下载大图
  2. 使用工具压缩图片
  3. 删除重复图片
  4. 查找复用相似图片

方式1需要推动落地,所以本文不讨论这种处理方式。

图片压缩

为什么png能够无损压缩?
UI 同事提供的PNG图片,一般都是photoshop导出的,图片存在大量的额外信息。
png图片有两种类型的数据块,

  • 一种是必不可缺的数据块称为关键数据块。
  • 另一种叫做辅助数据块,辅助数据块在png文件中占据了极大的篇幅,正是这些数据块构成了png的无损压缩条件

工具推荐:ImageOptim图压 、tinypng
tinypng进行无损压缩,压缩率一般在60%-70%之间,非常高效,缺点是只能线上压缩

图片资源压缩也有很多公司使用webp格式图片,这种格式对比pngjpg要小很多,但客户端性能对解码webp图片会有一定的影响。在一些老的机型上,表现不是很好。所以需要做一些取舍。这里有webppng格式转换的工具 isparta

其实我觉得这两种方案可以共存,团队内部设定一个资源文件的最大值,比如超过 100KB 就选择使用 webp格式的图片,小于 100KB 就使用压缩工具。这样就可以极大的减少资源文件的大小,同时减少包的体积。

删除重复图片

通常来说,出现重复图片的原因包括 模块间需求开发没有打通 或是 缺少统一的图片命名规范。通过图片MD5摘要是识别重复图片的最快方法
也可以使用工具 LSUnusedResources 进行处理

代码文件优化

代码文件优化其实可以看成是对可执行文件 Mach-O 的优化,其大小是由代码量决定的。所以对 Mach-O 瘦身,其实就是查找并减少无用的代码

无用代码检测

检测工具:WHC_Scan (使用说明)fui工具

减少第三方SDK

  • 检查是否导入了相同的功能的库
  • 第三方库大小占比很高时,考虑是否要替换掉它

编译优化

修改 Build Setting 的相关配置,可以让我们在更快的编译速度、更小的二进制大小、更快的执行速度之间自由选择。这种方式的性价比很高,改动一项配置,就可能会带来收益,但是可能具有一定的风险,需要谨慎。

  1. Build Settings -> Architectures -> Excluded Architectures 删除无用架构
  • 模拟器 32 位处理器测试需要 i386 架构;
  • 模拟器 64 位处理器测试需要 x86_64 架构;
  • 真机 32 位处理器需要 armv7, 或者 armv7s 架构;
  • 真机 64 位处理器需要 arm64 架构。
    删除无用架构

    结论:
    该编译项在 Release 下的配置应如下
    Any iOS SDK 设置为armv7 / &armv7sAny iOS Simulator SDK 设置为arm64
    意思是Release模式下真机排除armv7 和 armv7s指令集,模拟器排除arm64(模拟器不支持arm架构)
  1. Build Setting - Link-Time Optimization 链接时优化 LTO(Link-Time Optimization)
    对整个程序代码进行的一种优化,是 LLVM 里在链接时进行跨模块间的优化。

LTO 优化的优点:
一、将一些函数內联化:不用进行调用函数前的压栈、调用函数后的出栈操作,提高运行效率与栈空间利用率;
二、去除一些无用代码:如果一段代码分布在多个文件中,但是从来没有被使用,普通的 -O3 优化方法不能发现跨中间代码文件的多余代码,因此是一个局部优化。但是 Link-Time Optimization 技术可以在 link 时发现跨中间代码文件的多余代码;
三、对程序有全局优化作用:这是一个相对广泛的概念。举个例子来说,如果一个if 方法的某个分支永不可能执行,那么在最后生成的二进制文件中就不应该有这个分支的代码。

LTO 优化的缺点:
一、LTO 会降低编译链接的速度,所以建议在打正式包时开启;
二、开启了 LTO 之后,Link Map 的可读性明显降低,多出了很多数字开头的类(LTO 的全局优化导致的),所以如果需要阅读 Link Map,可以先关闭 LTO;


LTO优化

有三种选项可供选择:
No: 默认项,不开启链接期优化
Monolithic: 生成单个LTO 文件,每次链接重新生成,无缓存高内存消耗,参数 LLVM_LTO=YES
Incremental: 生成多个LTO 文件,增量生成,低内存消耗,参数 LLVM_LTO=YES_THIN

结论:
该编译项 Release 模式下应将 Link-Time Optimization 设为 Incremental

  1. Code Generation -> Optimization Level 语言编译优化
  • OC 优化:Build Settings -> Apple Clang - Code Generation -> Optimization Level
  • Swift 优化:Build Settings -> Swift Compiler - Code Generation -> Optimization Level
语言编译优化

OC 内联优化参数如下:

  • None[-O0]:Debug 模式下默认开启,编译器不会优化代码,意味着更快的编译速度和更多的调试信息
  • Fast[-O, O1]:编译器会优化代码性能并且最小限度影响编译时间,此选项在编译时会占用更多的内存
  • Faster[-O2]:编译器会开启不依赖空间 / 时间折中所有优化选项。在此,编译器不会展开循环或函数内联。此选项会增加编译时间并且提高代码执行效率
  • Fastest[-O3]:编译器会开启所有的优化选项来提升代码执行效率。此模式编译器会执行函数内联使得生成的可执行文件会变得更大。不推荐使用此模式
  • Fastest Smallest[-Os]:编译器会开启除了会明显增加包大小以外的所有优化选项。默认在 Release 模式下开启
  • Fastest, Aggressive Optimization[-Ofast]:启动 -O3 中的所有优化,可能会开启一些违反语言标准的一些优化选项。不推荐使用此模式
    结论
    使用默认配置即可,无需修改

Swift 编译内联优化参数如下:

  • No optimization[-Onone]:Debug 模式下默认开启;不进行优化,能保证较快的编译速度
  • Optimize for Speed[-O]:Release 模式下默认开启;编译器将会对代码的执行效率进行优化,一定程度上会增加包大小
  • Optimize for Size[-Osize]:编译器会尽可能减少包的大小并且最小限度影响代码的执行效率。
    核心原理:是对重复的连续机器指令外联成函数进行复用,和函数内联的原理正好相反。因此,将其开启,能减小二进制的大小,但同时理论上会带来执行效率的额外消耗,对性能(CPU)敏感的代码使用需要评估
    配合其使用的还有Compilation Mode设置,其含有两个选项
    1、Single File:单个文件优化,可以减少增量编译的时间,并且可以充分利用多核 CPU,并行优化多个文件,提高编译速度。但是对于交叉引用无能为力
    2、Whole Module:模块优化,最大限度优化整个模块,能处理交叉引用。缺点不能利用多核 CPU 的优势,每次编译都会重新编译整个 Module
    Relese 模式下 -Osize 和 Whole Module 同时开启效果会发挥的最好
    结论:
    Release 模式下配置为 Optimize for Size[-Osize]Compilation Mode选项改为Whole Module
  1. Swift Compiler - Code Generation -> Compilation Mode 编译模式优化
    编译模式优化

结论:Release 模式下配置为Whole Module

  1. Linking -> Dead Code Stripping 清除无用代码
    清除无用代码

构建完成后,如果是 C、C++ 等静态的语言的代码、一些常量定义,如果发现没有被使用到将会被标记为 Dead code。开启 DEAD_CODE_STRIP = YES 这些 Dead code 将不会被打包到安装包中

结论:默认配置即为 YES,所以使用默认配置即可,无需修改。

  1. Deployment -> Strip Style 去除符号
    Strip Style

表示的是我们需要去除的符号类型的选项,其分为三个选择项:

  • All Symbols: 去除所有符号,一般是在主工程中开启;
  • Non-Global Symbols: 去除一些非全局的 Symbol(保留全局符号,Debug Symbols 同样会被去除),链接时会被重定向的那些符号不会被去除,此选项是静态库 / 动态库的建议选项;
  • Debug Symbols: 去除调试符号,去除之后将无法断点调试。
    结论:主工程选择All Symbols,静、动态库选择Non-Global Symbols

其他

  • LinkMap 可以得出每个类或者库所占用的空间大小(代码段+数据段),方便开发者快速定位需要优化的类或静态库 (用这个我找到了一个非常大的背景图,2x的2M,3x的将近4M)删除后效果非常明显

参考
图片减包
iOS开发之ipa瘦身初探
iOS 优化 - 瘦身
搜狐技术:iOS包体积优化实践

推荐一个好用的工具:
WBBlades重要节点更新-专为提效而设计
基于Mach-O文件解析的工具集,包括无用代码检测(支持OC和Swift)、包大小分析(支持单个静态库/动态库的包大小分析)、点对点崩溃解析(基于系统日志,支持有符号状态和无符号状态)。主要利用了__Text汇编代码分析、架构提取、符号表剥离、DYSM文件提取、崩溃文件(ips)解析等技术手段实现。

图片相似度对比原理:像素差异比对;神经网络算法;感知哈希算法

https://www.beyondcompare.cc/jiqiao/bc-iaitpdnb.html
https://blog.csdn.net/SummerCloudXT/article/details/82629348

图片优化
https://mp.weixin.qq.com/s/R1XLp9hjHDBdYcOI6w8psw?st=6549E4933ED5189346545894F2A78782F20FCC794D3AABAFEC71B28EE5137DCBAED3EF66F3ABAA12D883A0CFAFFAF9674735DDFE7FF8FF330EC203623400F7AC46B764E56A2A6C976B86463B579E6679258A5F901A28EBDA115C028002C6298405AE50DB2E289D8EDAB7665F725D0F9915C004B50F543EC91F167DAD9F39BEB7D04BD3D3F9C326F45D041DE02EED051A70A32C319BA456224F319DA15120E6F87DE7E20AA4E6EF5AAEA7F1A7163375BB310B3764C09F2BDBB85DBBC9C070FF998F5C1E3287939571FFAD93B934D4CDF4A767DC16039F496CAB69A60682FB79B142BA97832DB6FC2BC586B556566FD97B&vid=1688850554212014&cst=23243E3C24F0F0F6A72AC9CACE56273717B121DDA305387260038FF4C4B66AB902AF3BF775A8293886EC9E7D122DF1F5&deviceid=bd743fd4-27e5-443b-beb6-d2ade5027ff6&version=4.0.16.70139&platform=mac

WWDC22 App 包大小优化
https://xiaozhuanlan.com/topic/4675012938

[代码管理工具](https://juejin.cn/post/7185083491061596219/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容

  • 文章链接 经过多个版本迭代,项目在release配置下的打包体积依旧轻松破百,应用体积过大导致的问题包括: 更长的...
    sindri的小巢阅读 1,699评论 3 17
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,082评论 1 32
  • feisky云计算、虚拟化与Linux技术笔记posts - 1014, comments - 298, trac...
    不排版阅读 3,813评论 0 5
  • 1。 不要试图赠诗于我。不要把轻浮与浅薄当成枝头的果。从不艳羡暧昧的红色。比之喧哗的街,我更喜欢默默含翠,无声凋落...
    风轻语阅读 389评论 2 7
  • 无论社会发展到哪个阶段,钱是离不了的,挣钱是硬道理,那如何赚到更多的钱,普通人,需要时刻关注,挖掘自身的市场...
    b367b34761cd阅读 246评论 0 1