包体积优化实战

前言:

随着业务的快速迭代增长,App里不断引入新的业务逻辑代码、图片资源和第三方SDK,直接导致APK体积不断增长。怎么来优雅的解决包体积问题呢?接下来就带来我的一些见解。

在新氧8.24.0版本的对比情况

对比主流app

一. 为什么要优化包体积

1.下载转化率

安装包体积与下载转化率的关系图

从图来看,安装包越小,转化率越高的结论依然成立。一个100MB的应用,即使用户点击了下载,也可能因为下载时间过长,网络速度慢,手机存储紧急等原因而中途终止下载,正如图中所描述,安装包大小与转化率的关系是非常微妙的。

2.推广成本

包体积对渠道推广和厂商预装的单价会有非常大的影响。特别是厂商预装,这主要是因为厂商留给预装应用的总空间是有限的。如果你的包体积非常大,那就会直接增加公司市场推广成本。

3.安装时间

文件拷贝、Library 解压、编译 ODEX、签名校验等,新氧app的dex数量高峰时存在24个dex,在android5.0,6.0系统的低端机型上安装时间长达2分钟左右,给用户带来不好的安装体验

4.运行内存

Resource 资源、Library 以及 Dex 类加载这些都会占用不少的内存。新氧app的初始运行内存就高达160MB。

5.存储空间

100MB 的安装包,启动安装解压之后很有可能就超过 200MB 了。对低端机用户来说,也会有很大的压力。

6.业务梳理

删除无用或者低价值的业务,回顾过去的的业务,不能只顾着往前冲,适时地还一些‘技术债务’

二. 如何优化包体积?

首先,我们来看看安装包的组成,无非就是Dex、Resource、Assets、Library 以及签名信息这五部分,包体积优化就是对这五部分进行优化的过程,接下来就进行优化阶段。


新氧app组成
apk组成

1.Dex优化

1.代码混淆ProGuard

常言道,“十个 ProGuard 配置九个坑”,特别是各种无良的第三方 SDK。面对ProGuard 配置文件,我们需要仔细检查,寻找是否存在过度keep的现象。

新氧ProGuard 配置文件过度keep现象

实际上,很多情况下我们只需要 keep 其中的某个包、某个方法,或者是类名就可以了。值得注意的是针对被反射使用到的类需要被keep。

我们还可以尝试开启R8的完全模式,在完全模式下能更加彻底的删除无用代码

2.去掉 Debug 信息或者去掉行号


dex格式

某个应用通过相同的 ProGuard 规则生成一个 Debug 包和 Release 包,其中 Debug 包的大小是 4MB,Release 包只有 3.5MB。

既然它们 ProGuard 的混淆与优化的规则是一样的,那它们之间的差异在哪里呢?那就是 DebugItem。

DebugItem 里面主要包含两种信息:1,调试的信息。函数的参数变量和所有的局部变量。2,排查问题的信息。所有的指令集行号和源文件行号的对应关系

DebugItem有多大? 占了dex文件的5.5%左右,去掉DebugItem不影响整个的运行逻辑和性能,甚至还能降低一点运行内存。

如何删除DebugItem? Facebook 的一个开源编译工具ReDex可以做到去掉DebugItem,感兴趣的可以去认真研究下

3.Dex分包

新氧的dex文件

新氧apk高峰期中有24个dex文件,为啥会有这么多的dex文件呢?原因是

“define classes and methods”是指真正在这个 Dex 中定义的类以及它们的方法。而“reference methods”指的是 define methods 以及 define methods 引用到的方法。

从图上来看,有2800多个方法是引用其他Dex的方法,这些跨 Dex 调用会造成一些冗余信息,这些冗余信息又会造成method id 爆表,信息冗余等问题。


定义一个Dex 信息有效率的指标, 每个 Dex 的方法数都是满的,即分配了 65536 个方法。保证 Dex 有效率应该在 80% 以上。

Dex信息有效率 = define methods数量/reference methods数量      reference methods数量 = 65536

那如何实现 Dex 信息有效率提升呢?关键在于我们需要将有调用关系的类和方法分配到同一个 Dex 中,即减少跨 Dex 的调用的情况。Facebook的ReDex使用的是贪心算法计算局部最优值。感兴趣的可以去认真研究下

2.Native Library优化

1.Library压缩

在默认的 lib 目录,我们只需要加载少数启动过程相关的 Library,其他的 Library 我们都在首次启动时解压。对于 Library 格式来说,XZ 或者 7-Zip 压缩的压缩率同样可以比 Zip 高 30% 左右,效果十分惊人。压缩方案的缺点在于首次启动的时间。

2.Library动态加载

目前市面上有大量成熟方案,比如SoLoader, ReLinker等,我们可以借助这些成熟方案来实现so的动态加载,不过我们要注意安全性问题,对外部路径下so文件必须要做安全性检查。还有处理好版本控制问题,做到so文件和APK版本一致。so文件动态加载的优化效果十分显著,同时也要注意崩溃率,用户体验等问题

3.去掉无用so文件

随着业务的不断更新换代,有些业务已经被弃用了,但是无用so文件还依旧保留在项目中,如果没有时常对so文件进行筛选,这些无用so文件会一直在项目里吃灰,占用了很多体积。在新氧做包体积优化期间,筛选并去掉了11个so文件,节省了大约5M的体积。 为了不用每次等到包体积专项整治的时候才能做这个工作,项目中需要健全so文件增量机制,将so文件文档管理等措施来完善

3.Resource优化

1.图片资源优化

项目中存在了高达十几M的图片资源,单张图片最大的有超过600Kb的情况,怎么让这些大体积图片在设计能接受的情况下变小呢?答案是压缩和格式转换,对png图片进行压缩操作,tinyPng就是把相似像素的24bit位用8bit位来表示,并且移除了不必要的元数据,肉眼很难看出来变化。格式转换:将没有透明通道的png图片转换成jpg图片,图片体积上会有极大的提升,也可以将少量透明通道的png图片转换成webp图片,也能做到图片体积的减少。不仅是要做到对存量图片进行处理,也要对增量图片进行防范,制定增量规则,对增量图片自动化压缩,大体积图片警告等措施来完善

2.资源混淆和极限压缩 

资源混淆的思路其实非常简单,就是把资源和文件的名字混淆成短路径。这样做的好处是 1.资源索引文件 resources.arsc 需要记录资源文件的名称与路径,使用混淆后的短路径 res/s/a,可以减少整个文件的大小。2.metadata 签名文件记录了所有文件的路径以及它们的哈希值,使用短路径可以减少这两个文件的大小。3.ZIP 文件格式里面也需要记录每个文件 Entry 的路径、压缩算法、CRC、文件大小等信息。使用短路径,就可以减少记录文件路径的字符串大小。

资源文件有一个非常大的特点,那就是文件数量特别多。以新氧 8.26 为例,安装包中就有 13000 多个资源文件。

apk使用的还是 Zip 算法,AndResGuard利用了7-Zip 的大字典优化,APK 的整体压缩率可以提升 3% 左右。同时也支持针对 resources.arsc、PNG、JPG 以及 GIF 等文件的强制压缩。

3.无用资源

通过长时间的迭代,项目总会有一些无用的资源,尽管它们在程序运行过程不会被使用,但是依然占据着安装包的体积。那我们就可以使用Lint静态代码扫描工具来进的无用资源了。不过项目里还存在很多动态加载资源,跨module使用资源的情况,导致这部分资源需要谨慎处理。

三. 怎样持续优化包体积?

1.制定规范

规范永远都是让开发效率时半功倍的,不管是代码规范,资源规范,接入第三方库规范等都能让项目的包体积得到改善,比如除特殊情况,超过50kb的图片不得添加到项目中,调研第三方库时对带来的体积进行审核,代码尽量做到复用性,而不是省事的复制一份,无用业务的删除资源,超过2M的功能需要审核等操作都能有利于包体积优化

2.持续监控

对于包体积,如果一直放任不管,几个版本后就能给你一个很大的惊喜,通常有这些方式进行监控:

1.大小监控:每个版本跟上一个版本包体积的对比情况。如果某个版本体积增长过大,需要分析具体原因,是否有优化空间。

2.依赖监控:每一版本我们都需要监控依赖,这里包括新增 JAR 以及 AAR 依赖。这是因为很多开发者非常不细心,经常会不小心把一些超大的开源库引进来。

3.规则监控:将包体积的监控抽象为规则,例如无用资源、大文件、重复文件、R 文件等,比如使用微信开源的ApkChecker实现包体积的规则监控。

3.监控的自动化和平台化

包体积的监控最好可以实现自动化与平台化,作为发布流程的其中一个环节。不然通过人工的方式,很难持续坚持下去。

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

推荐阅读更多精彩内容