一.前语
App装置包日益增大原因
跟着技能飞速发展,功用不断迭代,APP不断更新和改版,越来越大、越来越全,因而造成了app装置包的不断胀大。
- 新功用的添加:新的功用需求更多的代码和资源来实现,导致APP体积增大。
- 针对不同设备的优化代码:为了在各种不同分辨率和硬件渠道的手机上正常运用,APP需求针对每种设备分别编写优化代码。这种“碎片化”代码会包括许多冗余代码,然后添加软件体积。
- 硬件设备标准的改动:当硬件设备的某些标准改动后,APP也必须做出相应的改动,这通常会导致APP体积增大。例如,当iPhone的屏幕分辨率进步后,APP需求适配新的分辨率,导致界面资料的部分需求占用更大的存储空间。
- 优先适配旗舰机:大部分APP在测试时优先适配旗舰机,这会导致在低端机上运用时或许出现不流通或闪退等问题,而高端机则不会出现这些问题。
装置包巨细首今夕比照
为什么要优化包巨细
在精细化运营的角逐中,用户体会、版别更新、内容品质、装置包巨细等要素都影响着移动运用厂商的生存状况。特别是装置包体巨细,无论是手游仍是移动运用,包体变大不只联系着用户下载转化,也联系着渠道推行本钱和难度,在全体大盘用户规模增加的状况下,运用获量的竞争日益激烈,有40.8%的开发者以为投入产出比相关于上一年同期出现下降趋势,51.5%的开发者以为,与上一年同期比较运用产品的获客本钱单价有所上升,这是用户获取本钱的添加与付费才干的约束。(来自网络)
比照举例
为什么微信小程序比较app 有更好的转化和推行才干呢,其实有很大原因也是由于用户能快速运用装置
微信小程序与APP比较有以下优势:
- 无需下载和装置:微信小程序能够直接在微信中运用,无需下载和装置,这样能够节约用户的存储空间和下载时间。
- 快速加载:微信小程序选用轻量级的技能架构,加载速度快,用户能够快速翻开运用。
- 无需更新:微信小程序能够在后台自动更新,用户无需手动更新运用程序。
- 便于共享:微信小程序能够经过微信共享给老友、群组或朋友圈,方便用户共享运用程序。
- 轻量级:微信小程序相关于App来说,占用的存储空间更小,对手机功能的耗费也更少。
- 跨渠道:微信小程序能够一起运转在ios和Android渠道上,无需为不同渠道开发不同版别的运用程序。
总之,微信小程序比较APP具有无需下载装置、快速加载、无需更新、便于共享、轻量级、开发本钱低、跨渠道等优势。
因而相关于小程序 来说,app 假如想更好的发挥转化运用率等要素,就需求在装置包上下功夫了。
官方数据
此外包体巨细每上升6MB,运用下载转化率就会下降1%
数据来在2019谷歌开发者大会上
谷歌给出了一个很详细的数据,包体巨细每上升6MB,运用下载转化率就会下降1%。不同地区转化率略有差异,APK包体巨细每削减10MB ,全球平均下载转化率会提高1.75%,新兴国家代表印度和巴西下载转化率提高2.0%以上,高端商场代表美国和德国下载转化率提高1.5%。
其他要素
developer.apple.com/help/app-st…
App Store OTA 下载巨细约束
苹果公司为了防止用户超出运营商套餐流量,约束了用户经过流量从 AppStore 下载 App 的最大巨细, 简称 OTA 下载巨细约束。其历史沿革:
- 2017 年 9 月,约束从 100MB 提高到了 150MB;
- 2019 年 5 月下旬,苹果把 OTA 下载约束放宽到 200MB;
- iOS 13 发布之后 iOS13 及以上用户能够运用流量下载超出 200MB 的 App, 但需求用户「设置」挑选策略,默以为「超越 200MB 恳求答应」,而 iOS13 以下用户依然无法下载。
除了上边的约束之外 Apple 对可执行文件__TEXT 段的约束则更为严苛,假如超出这个约束 APP 将无法经过 AppStore 审阅。这个约束简而言之,假如要支撑 iOS8 的设备, App 单架构主二进制 __TEXT 段上限为 60MB(以 1000KB 为 1M,而不是 1024),抛弃对 iOS8 的支撑二进制巨细约束则变为装置包内最大二进制一切架构的总和不超越 500MB。
装置包巨细增加的影响
AppStore 下载巨细假如在 OTA 下载约束内增加,对用户新增、留存等方针影响不大。而一旦超越 OTA 下载约束,则对全体方针发生明显影响。之前统计的劣化数据方针:当约束在 150MB 并且无法下载的时分,对用户的新增有 10%的影响。由于 iOS13 约束的宽松化,所以在 iOS13 之后设备上这个数据将低于 10%。此数据仅供参考并不能混为一谈,关于不同类型的 App 初次装置的场景会出现差异,比方生活服务、出行类 App 对应蜂窝下载场景会多于影音类、游戏类 App。
其次对依然需求支撑 iOS8 以下的 App, 超出 __TEXT 段巨细的约束将会很大程度上影响审阅以及发版进展。当然能够经过一些手法进行救急,比方拆分动态库的办法绕过。可是这些手法或许导致装置包全体变得更大。
除了 Apple 的约束外,包巨细的劣化必定程度上意味着更加慢的发动速度;更多的的代码逻辑;更低研发效率;过于复杂的代码还会带来对代码修正的危险将对稳定性发生负面影响;让功能等基础体会变差,所以包巨细不是一个孤立的方针,它从旁边面的反映出 App 的健康状况。
综上,关于用户来说装置包巨细是一个十分重要的方针,装置包资源巨细优化是十分重要的。
二.苹果对装置包做的优化
help.apple.com/xcode/mac/c…
App Store和操作体系优化了iOS、tvOS和watchOS运用程序的装置,依据用户特定设备和操作体系版别的功用定制运用程序交付,以最小的占用空间。这种优化被称为运用精简,允许你创立运用最多设备功用,占用最小磁盘空间,并适应苹果未来或许运用的更新的运用。更快的下载速度和更多的空间为其他运用程序和内容供给了更好的用户体会。
Slicing (iOS, tvOS)
针对不同方针设备和操作体系版别创立和发布运用包变体的过程。变体只包括方针设备和操作体系版别所需的可执行体系结构和资源。你能够继续开发并将运用的完好版别上传到app Store Connect。App Store会依据你的运用支撑的设备和操作体系版别,创立并发布不同的版别。运用资产目录,以便App Store能够为每个变体挑选图画,GPU资源和其他数据。当用户装置运用程序时,将下载并装置用户设备和操作体系版别的变体。
在运转iOS和tvOS 9.0及更高版别的设备上支撑切片运用。否则,App Store会向用户供给通用版别。通用版别也能够经过移动设备办理(MDM),经过Apple School Manager或Apple Business Manager批量购买的运用程序,或运用iTunes 12.6或更早版别下载的运用程序供给。
关于在 AppStore 发布的包,苹果也为 App 供给了许多优化办法,而这些是经过企业证书签发的包无法做到的。
当 App 构建完装置包之后上传到 AppStore Connect 后, AppStore Connect 会依据设备、体系来创立其变体(variant)以适配不同的设备,用户从 App Store 中下载到的装置包时分,只下载自己设备用到变体。
变体之间的差异取决于设备的处理器架构(arm64, armv7)、屏幕分辨率(2x, 3x)、iOS 体系版别。
当然这也导致很难用线下构建的装置包来量化终究对下载巨细的影响。
Bitcode
位码是已编译程序的中间表明办法。你上传到App Store Connect的包括位码的运用程序将被编译并链接到App Store上。包括位码将允许苹果在未来重新优化你的运用二进制,而无需向app Store提交新版别的运用。
关于iOS运用程序,比特码是默许的,但也是可选的。关于watchOS和tvOS运用程序,需求位码。假如你供给了bitcode,那么app bundle中的一切运用和框架(项目中的一切方针)都需求包括bitcode。
Xcode默许隐藏运用程序的符号,所以苹果无法读取它们。当你将运用上传到app Store Connect时,你能够挑选包括符号。当你运用TestFlight或经过app Store发布运用时,包括符号能够让苹果为你的运用供给溃散陈述。假如你想自己搜集和符号溃散陈述,你不需求上传符号。相反,您能够在发布运用程序后下载位码编译dSYM文件。
按需资源(iOS、tvOS)
按需资源是指能够用关键字符号并按符号分组恳求的资源(例如图画和声响)。App Store托管苹果服务器上的资源,并为你办理下载。App Store还按需分割资源,进一步优化运用的变体。
按需资源供给更好的用户体会:
-
运用尺度更小,所以下载速度更快,改善了初次发布的体会。
-
当用户阅读运用程序时,依据需求在后台下载按需资源。
-
操作体系在不再运用或磁盘空间缺乏时整理按需资源。
例如,运用程序能够将资源划分为等级,并仅在运用程序预计用户将移动到下一等级时恳求下一等级的资源。同样,只有当用户进行了相应的运用内购买时,运用才干恳求运用内购买资源。
综上苹果架构优化首要体现在
关于指令集
x86_64 和 i386,是用于模拟器的芯片指令集架构文件;arm64、armv7、armv7s ,是真机的芯片指令集架构文件。
-
运用 App Thinning 后,用户下载时就只会下载一个适宜自己设备的芯片指令集架构文件。App Thinning 有三种办法,包括:App Slicing、Bitcode、On-Demand Resources。
-
App Slicing,会在你向 iTunes Connect 上传 App 后,对 App 做切开,创立不同的变体,这样就能够适用到不同的设备。
-
On-Demand Resources,首要是为游戏多关卡场景服务的。它会依据用户的关卡进展下载随后几个关卡的资源,并且现已过关的资源也会被删掉,这样就能够削减初装 App 的包巨细。
-
Bitcode ,是针对特定设备进行包巨细优化,优化不明显。
三.优化准备工作
剖析装置包组成
四.技能计划
资源优化
大资源优化
资源是指plist、js、css、json、端智能模型文件等,因这些文件和图片在优化办法差异很大,所以把两者区分开来。获取大资源首要途径是递归遍历ipa包的一切资源,体积大于指定阈值(一般20-40kb)的文件便是需求对其优化的文件
github.com/fndppx/Prac…
经过扫描能够看到对应超越阈值的文件:
此外能够对其他大资源,比方皮肤资源,h5缓存文件等选用下载zip包办法获取,下载成功后适宜的机遇解压。
- 异步下载:只需APP初次发动时不需求加载该资源,或许即使初次发动需求加载可是运用频率不高,那么该资源就能够走异步下载;
- 资源紧缩:当APP初次发动需求加载且频率较高的状况下,能够对大块资源先进行紧缩内置APP,发动阶段异步线程解压再运用;
无用配置或许图片文件
针对特定的配置文件类型非必要的进行扫描,自己操控类型,如扫描图片和 html 文件目录是否有其他类型文件
针对图片资源首先将png、webp、gif、jpg扫除掉,JS&CSS资源是一般HTML加载的,关于需求扫描图片资源目录经过扫除
github.com/fndppx/Prac…
重复资源优化
github.com/fndppx/Prac…
指定目录或许从iPA包中获取一切资源文件,经过MD5判断资源是否重复
图片优化
无用图片优化: 依据开源东西扫描
LSUnusedResources
怎么扫描的
-
在文件夹[imageset, launchimage, appiconset, bundle, png]中获取资源文件(默许:[imageset, jpg, png, gif])。
-
运用正则表达式搜索代码文件中的一切字符串称号(默许值:[h, m, mm, swift, xib, storyboard, strings, c, cpp, html, js, json, plist, css])。
-
从资源文件中扫除一切运用的字符串称号,咱们得到一切未运用的资源文件。
Asset Catalog图片优化
之前在bundle需求放二倍图和三倍图,同一张图片终究在用户手机上会有两份,iOS7体系有了Asset Catalog后,Asset Catalog为不同类型设备(分辨率不同)或许相同类型设备但不同配置(磁盘不同)供给定制化资源下载,当用户下载App时,只有跟用户手机硬件设备参数相匹配的资源才会被下载,其他不会下载,然后降低下载包体积;
优势
-
包体积减肥
-
统一的图片无损紧缩
-
便利的资源办理
-
高效的I/O操作
苹果官方比照:
HEIC图片优化
更改PNG和JPEG图片编码格局,挑选HEIC计划,依据以下长处:1、体积最小,HEIC比PNG体积削减50%,WebP比PNG优化30%;2、解码效率高,跟WebP比较,HEIC硬解码效率高,略慢于JPEG;
HEIC(High Efficiency Image Coding)是一种图画编码标准,它能够极大提高紧缩率,并有效减小储存占用,自iOS 11和macOS High Sierra(10.13)开端,苹果将HEIC设置为图片存储的默许格局,它由动态影像专家小组(MPEG)开发,并在MPEG-H Part 12(ISO/IEC 23008-12)中界说,以下是HEIC图片的特点:
紧缩率高:HEIC图片比JPEG图片紧缩率高1.5倍,比PNG图片紧缩率高3倍,也比GIF图片紧缩率高3倍。
节约内存:HEIC图片比JPEG图片节约20%的存储空间,比PNG图片节约50%的存储空间,比GIF图片节约80%的存储空间。
解码效率高:在iOS体系中,HEIC选用硬解码,解码效率高,跟WebP(软编码)比较,是其100倍,但略慢于JPEG。
保存原始图画质量:HEIC图片选用H.264和JEP格局紧缩,能够保存原始图画质量。
支撑无损扩大:HEIC图片支撑无损扩大,能够将图片扩大两倍而不失真。
颜色处理方面: HEIC图片能够依据像素点的亮度散布自动亮度、比照度和饱和度,然后更好地还原图画的真实颜色。
体系兼容性好:咱们知道iOS 11开端HEIC是图片存储的默许格局,也便是iOS 11以后的体系都支撑HEIC图片,对这部分用户怎么处理?在实践中发现,在iOS10体系上,当把HEIC图片放xcasset文件里,终究图片也是能够正常显现的,用Asset Catalog Tinkerer东西解压出Assets.car 文件,发现在xcasset里的HEIC图片,关于iOS10的体系,在打包时会被体系转化为png格局图片,Asset Catalog解决了HEIC图片的兼容性问题。
怎么运用
代码加载和png无差异
UIImageView *img = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"test_image_h"]];
[self.view addSubview:img];
img.frame = CGRectMake(100, 100, 200, 100);
- 关于大图HEIC格局明显体积小
理论上来说,HEIC格局图片的体积是PNG格局图片的三分之一,但实际过程发现关于大图,这个优化作用很明显,可是关于小图尤其是小于10K的图片,HEIC图片还有或许超越PNG格局图片,所以咱们在做HEIC图片编码优化时,关于小图不主张用这种办法。
- 带有Alpha通道的PNG图片不要做有损紧缩
在实践过程中发现,一张PNG原图,尤其是带有Alpha通道,经过有损紧缩(TinyPng或ImageOptim)后,再生成HEIC图片时,在iOS12,13,14体系上会显现绿幕,所以带有Alpha通道的PNG图片不要做有损紧缩,存在兼容性问题。
转化完成最好要测试下确保不会出现异常加载失利的问题
WebP****紧缩优化
HEIC是iOS12以后推出来一种新格局,关于带有Alpha通道的并经过紧缩的PNG图片,转化为HEIC格局后,在iOS12和13体系存在兼容性问题,Alpha通道全变为0,为此关于这种case,尤其是大图,假如图片巨细超越了 100KB,能够考虑运用 WebP能够选用WebP紧缩优化;
来将其他图片转成 WebP
Google开发的
developers.google.com/speed/webp/…
腾讯开发的
isparta.github.io/
转化结束后显现图片时运用 libwebp 进行解析
github.com/carsonmcdon…
关于小于 100KB 时,你能够运用网页东西 TinyPng 或许 GUI 东西ImageOptim进行图片紧缩。
TinyPng紧缩
WebP 在 CPU 耗费和解码时间上会比 PNG 高两倍,由于关于大于100KB的图片能够运用 WebP,关于小于 100KB 图片,运用TinyPng进行紧缩,虽然紧缩率没有 WebP 那么高,可是没有改动图片编码办法,所以不会添加解析功能损耗。
编译器优化 & xcode架构优化
xcode14优化
Xcode 支撑 ****XCode14的晋级对包体积带来比较明显的优化,官方给出数据是运用程序下载包体积减小了 30%
编译器优化
代码优化
LinkMap查看每个类占用巨细
https://github.com/jayden320/LinkMap
Link Map 是 Mach-O 格局的二进制文件的一种辅助文件,它描绘了可执行文件的全貌,包括编译后的每一个方针文件的信息以及它们在可执行文件中的代码段、数据段存储详情。经过Link Map文件,咱们能够知道可执行文件的途径、CPU架构、方针文件、符号等信息,剖析可执行文件中哪个类或库占用比较大,进行装置包减肥,此外,咱们能够清楚地了解可执行文件的内部结构和各个方针文件在其间的方位联系,这关于剖析和调试十分有协助。
Mach-O 查看
https://sourceforge.net/projects/machoview/
Object文件列表
Object文件列表列出了一切编译后的方针文件,包括.o文件和dylib库。每个方针文件都有一个对应的编号,经过该编号能够对应到具体的类,Symbols会用到此编号。
Section段表
section段表描绘了各个段在终究编译成的可执行文件中的偏移方位及巨细,包括代码段(TEXT)和数据段(DATA)。段表中榜首列是数据在文件的偏移方位,第二列是Section占用巨细,第三列是Segment类型,第四列是Section类型,关于Segment和Section
2.3.4Symbols
Symbols模块给出了类里边的办法在内存具体状况。其间
- 榜首列是办法起始地址,经过这个地址咱们能够查上面的段表;
- 第二列是巨细,经过这个能够算出办法占用的巨细;
- 第三列是归属的类(.o),值是具体编号,经过反查方针文件列表能够知道对应的类;
- 第四列是办法称号。
经过Symbols模块咱们能够剖析出来每个类对应办法的巨细。
静态查看
58开源的东西
github.com/wuba/WBBlad…
利用appcode 东西检测无用的代码
www.jetbrains.com.cn/objc/
用 AppCode 做剖析的办法很简单,直接在 AppCode 里挑选 Code->Inspect Code 就能够进行静态剖析。
-
无用类:Unused class 是无用类,Unused import statement 是无用类引入声明,Unused property 是无用的特点;
-
无用办法:Unused method 是无用的办法,Unused parameter 是无用参数,Unused instance variable 是无用的实例变量,Unused local variable 是无用的局部变量,Unused value 是无用的值;
-
无用宏:Unused macro 是无用的宏。
-
无用大局:Unused global declaration 是无用大局声明。
appcode缺陷
-
某些库里界说了未运用的协议会被判定为无用协议
-
假如子类运用了父类的办法,父类的这个办法不会被以为运用了;经过点的办法运用特点,该特点会被以为没有运用;运用 performSelector 办法调用的办法也查看不出来,比方 self performSelector:@selector(arrivalRefreshTime);
-
运转时声明类的状况查看不出来。比方经过 NSClassFromString 办法调用的类会被查出为没有运用的类,比方 layerClass = NSClassFromString(@“SMFloatLayer”)。还有以[[self class] accessToken] 这样不指定类名的办法运用的类,会被以为该类没有被运用。像 UITableView 的自界说的 Cell 运用 registerClass,这样的状况也会以为这个 Cell 没有被运用。
-
运用 AppCode 查看出来的无用代码,还需求人工二次确认才干够安全删除掉。
动态查看
运转时查看类是否真正被运用过
#define RW_INITIALIZED (1<<29)
bool isInitialized() {
return getMeta()->data()->flags & RW_INITIALIZED;
}
isInitialized 的结果会保存到元类的 class_rw_t 结构体的 flags 信息里,flags 的 1<<29 位记录的便是这个类是否初始化了的信息。而 flags 的其他位记录的信息,objc runtime 的源码,如下:
// 类的办法列表已修正
#define RW_METHODIZED (1<<30)
// 类现已初始化了
#define RW_INITIALIZED (1<<29)
// 类在初始化过程中
#define RW_INITIALIZING (1<<28)
// class_rw_t->ro 是 class_ro_t 的堆副本
#define RW_COPIED_RO (1<<27)
// 类分配了内存,但没有注册
#define RW_CONSTRUCTING (1<<26)
// 类分配了内存也注册了
#define RW_CONSTRUCTED (1<<25)
// GC:class有不安全的finalize办法
#define RW_FINALIZE_ON_MAIN_THREAD (1<<24)
// 类的 +load 被调用了
#define RW_LOADED (1<<23)
五.其他流程阶段防备
1.开发阶段图片巨细把关
运用前紧缩,命名标准,xcassets统一办理图片
2.经过Jenkins打包监控比照包巨细增加
总结:
经过上述对包巨细优化的布景和收益的理解,再到结合东西和流程计划找出其短板,依据自己项目的状况合理采取对应计划持续优化重视,才是需求长时间坚持做下去的。
感谢参考
mp.weixin.qq.com/s?__biz=Mzg…
/post/691631…