百度APP Android包体积优化实践(一)总览
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="https://mmbiz.qpic.cn/mmbiz_gif/5p8giadRibbOichNxgNgW2xyHYqnHnww2mnGT5PC84tpKOThGv2k88zXbdh8DTfA38RniadrhC3y4JagKaIEPTNPlQ/640?wx_fmt=gif&tp=webp&wxfrom=5&wx_lazy=1" style="width: 50%; margin-bottom: 20px;"></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">GEEK TALK</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><strong style="color: blue;">01</strong></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">前言</strong></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">此前百度APP<span style="color: black;">已然</span>具备基本的包体积优化机制、约束和<span style="color: black;">认识</span>,但<span style="color: black;">做为</span>巨舰型APP,业务的高速迭代仍然不可避免地造<span style="color: black;">成为了</span>包体积爆炸式增长。包体积或直接或间接地影响着下载转化率、安装时间、运行内存、磁盘空间等<span style="color: black;">要紧</span>指标,<span style="color: black;">因此</span>投入精力扫除积<span style="color: black;">坏处</span>、发掘更深层次的体积优化项是<span style="color: black;">非常</span>必要的。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">按照</span>谷歌商店的内部数据,APK体积每减少10M,平均可<span style="color: black;">增多</span>~1.5%的下载转化率,如下图所示:</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="https://mmbiz.qpic.cn/mmbiz_png/Ce6bSqXkduycvJHvwubnw1P5p4pIIlia2L9znEDYOIic6Wstjklu3JibcHE2UBFPodjXb7eYBo8jFlibl8l1kbicoxg/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;"></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">图1 谷歌商店应用转化率<span style="color: black;">增多</span>幅度 / 10M</span><span style="color: black;"> </span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">Android包体积优化手段有<span style="color: black;">非常多</span>,<span style="color: black;">例如</span>业务裁剪、插件化、混合<span style="color: black;">研发</span>、资源后下发等。本系列<span style="color: black;">文案</span><span style="color: black;">重点</span>针对的是业务<span style="color: black;">没</span>关、集成在APK中的内容的体积优化,如Dex优化、资源优化、so优化等,<span style="color: black;">咱们</span><span style="color: black;">叫作</span>之为<span style="color: black;">基本</span>机制优化。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">包体积<span style="color: black;">基本</span>机制优化实践将会以系列<span style="color: black;">文案</span>的方式呈现,<span style="color: black;">重点</span><span style="color: black;">包含</span>以下部分:</span><span style="color: black;">心路历程、Dex行号优化完整<span style="color: black;">方法</span>、资源优化实践与探索、Dex优化实践与探索、so优化探索、其他优化经验与总结。</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">本文讲述的是百度APP包体积<span style="color: black;">基本</span>机制优化心路历程,<span style="color: black;">包含</span>起<span style="color: black;">连续</span><span style="color: black;">指点</span><span style="color: black;">功效</span>的基本思想、优化对象分析、对现有优化<span style="color: black;">工具</span>的学习、以及<span style="color: black;">最后</span>产出的体积优化项。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">GEEK TALK</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><strong style="color: blue;">02</strong></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">基本思想</strong></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">2.1 分而治之</strong></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">我</span><span style="color: black;">们的优化对象不只是APK这个<span style="color: black;">最后</span>产物,<span style="color: black;">亦</span><span style="color: black;">包含</span>APK中的内容,这些内容的体积优化思路与手段不尽相同。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">2.2 可<span style="color: black;">连续</span>优化</strong></p><span style="color: black;"><span style="color: black;">好的优化机制不止生效于当下,<span style="color: black;">亦</span>生效于<span style="color: black;">将来</span>。举例<span style="color: black;">来讲</span>,从源码仓库删除当前的Dead Code属于一次性存量优化操作,而编译器的DCE机制</span><span style="color: black;">(Dead Code Elimination)</span><span style="color: black;">可<span style="color: black;">连续</span>生效于<span style="color: black;">将来</span>产生的Dead Code。从长线<span style="color: black;">思虑</span>,<span style="color: black;">咱们</span>应优先<span style="color: black;">创立</span>后者,<span style="color: black;">而后</span>倒推前者的执行。</span></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">2.3 站在前人的肩膀上</strong></p><span style="color: black;">包体积优化并不是一个<span style="color: black;">鲜嫩</span>的<span style="color: black;">专题</span>,Android官方和<span style="color: black;">研发</span>者们都在<span style="color: black;">连续</span>致力于优化体积。重复造轮子是不被提倡的,但<span style="color: black;">针对</span><span style="color: black;">区别</span>的应用场景,尤其是巨舰型APP,体积优化应该有定制化的<span style="color: black;">方法</span>。</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">2.4 <span style="color: black;">知道</span>代价,有所取舍</strong></p><span style="color: black;"><span style="color: black;">按照</span>热力学第<span style="color: black;">必定</span>律,收益不会凭空产生,<span style="color: black;">必定</span>会<span style="color: black;">伴同</span>着代价,例如人力的投入、编译时间的<span style="color: black;">增多</span>、适配难度的<span style="color: black;">增多</span>等。<span style="color: black;">知道</span>代价后,<span style="color: black;">咱们</span><span style="color: black;">才可</span>决定某优化项<span style="color: black;">是不是</span>要做、何时做、<span style="color: black;">怎样</span>做。</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">2.5 约束与<span style="color: black;">认识</span></strong></p><span style="color: black;"><span style="color: black;">除了自动化的优化机制,还<span style="color: black;">必须</span>配套有自动化的体积增长约束,<span style="color: black;">同期</span>从源头<span style="color: black;">提高</span><span style="color: black;">研发</span>者的体积优化<span style="color: black;">认识</span>,多管齐下<span style="color: black;">才可</span>达到最优效果。</span></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">GEEK TALK</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><strong style="color: blue;">03</strong></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">APK结构分析</strong></p>
<h1 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">接下来<span style="color: black;">咱们</span>会简单分析下APK</span><span style="color: black;">内</span><span style="color: black;">各<span style="color: black;">构成</span>部分,</span><span style="color: black;">以及APK</span><span style="color: black;"><span style="color: black;">做为</span></span><span style="color: black;">ZIP,</span><span style="color: black;">其标准结构是什么样的。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">3.1 APK内容分析</strong></p>
</span></h1><img src="https://mmbiz.qpic.cn/mmbiz_png/Ce6bSqXkduycvJHvwubnw1P5p4pIIlia24LV0MLjOtiaah3AoZgwjEicz1IEyJlU02Lslyhm81F4Mc5JZNnrFFB7w/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;"><span style="color: black;">图2 APK 结构</span><span style="color: black;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">classes.dex</p>APK 中可能<span style="color: black;">包括</span>一个或多个 classes.dex 文件,应用程序内的 Java/Kotlin 源码<span style="color: black;">最后</span>会以 dalvik 字节码的方式存在于 classes.dex 文件中。
</span><span style="color: black;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">resources.arsc</p>该文件是<span style="color: black;">包括</span>配置信息的资源<span style="color: black;">查找</span>表,起着链接代码与资源的<span style="color: black;">功效</span>。Dex 文件中的 R.class 仅<span style="color: black;">包括</span>资源 id,AssetManager 会利用 id 到 arsc 表中<span style="color: black;">查找</span>与当前设备信息最匹配的资源文件路径(或资源内容)。
</span><span style="color: black;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">res/</p><span style="color: black;">包括</span>源码工程中 res 目录下除了 values 外的资源文件,这些文件路径<span style="color: black;">同期</span>会<span style="color: black;">表现</span>在 resources.arsc 中。
</span><span style="color: black;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">lib/</p>native libraries。即源码工程 jni 目录下的 so 文件,二级目录<span style="color: black;">必要</span>为 NDK支持的 ABI。
</span><span style="color: black;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">assets/</p>与 res/ 资源目录<span style="color: black;">区别</span>,assets/ 下的资源文件不会在 resources.arsc 中生成<span style="color: black;">查找</span>条目,且 assets/ 下的资源目录可完全自定义,业务代码获取 assets 资源和 res 资源的方式<span style="color: black;">亦</span>完全<span style="color: black;">区别</span>。
</span><span style="color: black;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">META-INF/</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">应用签名信息。该目录在应用签名后生成,<span style="color: black;">包括</span>以下三个文件:</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">MANIFEST.MF:摘要文件,<span style="color: black;">包括</span>APK内所有文件的路径及其 SHA1/SHA256 值。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">CERT.SF:对摘要的签名文件,<span style="color: black;">包括</span>APK内所有文件的路径,及其在 MANIFEST.MF 中对应信息的 SHA1/SHA256 值。</p>CERT.RSA:<span style="color: black;">保留</span>公钥、加密算法及其私钥加密后的内容。
</span><span style="color: black;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">AndroidManifest.xml</p>应用<span style="color: black;">名单</span>文件,用于描述应用基本信息,<span style="color: black;">重点</span><span style="color: black;">包含</span>应用包名、应用id、应用组件、所需权限、设备兼容性等。
</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">3.2 ZIP结构分析</strong></p><img src="https://mmbiz.qpic.cn/mmbiz_png/Ce6bSqXkduyAzb4te5F2rWPQC0rnTXvduric5gJTKW1lSkY5YAkOREYW83hnHjv9eSp2bfziawv9QjicL4kEjwQicQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;"><span style="color: black;">图3 ZIP 标准结构示意图</span><span style="color: black;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">压缩源文件信息</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Local file header:描述源文件信息。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">File data:源文件数据。</p>Data descriptor:校验码及压缩前后<span style="color: black;">体积</span>。
</span><span style="color: black;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">中心目录区</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Central directory</p>记录 ZIP 目录结构。每一条 file header 对应一个源文件,描述文件<span style="color: black;">关联</span>信息。
</span><span style="color: black;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">中心目录结束标识</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">End of central directory record</p>标识 ZIP 包结束,<span style="color: black;">包括</span> ZIP 包及中心目录的简要信息。
</span><span style="color: black;"></span><span style="color: black;"></span><span style="color: black;"></span><span style="color: black;"></span><span style="color: black;"></span><span style="color: black;"></span><span style="color: black;"></span><span style="color: black;"></span><span style="color: black;"></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">GEEK TALK</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><strong style="color: blue;">04</strong></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">现有优化<span style="color: black;">工具</span>介绍</strong></p><span style="color: black;"><span style="color: black;">针对</span>发展初期的应用,体积优化的优先级较低,直接<span style="color: black;">运用</span>以下体积优化<span style="color: black;">工具</span>是性价比最高的<span style="color: black;">选取</span>。百度APP <span style="color: black;">一样</span>对比借鉴了以下<span style="color: black;">工具</span>,从中衍生出了全新的、定制化的优化需求。</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">4.1 ProGuard</strong></p><span style="color: black;">在 AGP3.3 之前,ProGuard <span style="color: black;">做为</span>官方体积优化<span style="color: black;">工具</span>,负责在编译完成之后对class 文件进行缩减混淆等操作,其优化结果交给 Dx/D8 转化为 Dex 产物。</span><img src="https://mmbiz.qpic.cn/mmbiz_png/Ce6bSqXkduycvJHvwubnw1P5p4pIIlia2iaqjrPytY7vCYXYh30iahLHkzAxicPFjALOqZzr9x6eibCbiaY3XzYO29Fg/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;"><span style="color: black;"><span style="color: black;">图4 Proguard 处理对象及<span style="color: black;">功效</span>示意图</span><span style="color: black;"> </span></span><span style="color: black;">ProGuard 的优化操作<span style="color: black;">重点</span><span style="color: black;">包含</span>:</span><span style="color: black;"><strong style="color: blue;"><span style="color: black;">缩减</span></strong><span style="color: black;">:安全移除<span style="color: black;">没</span>用类、<span style="color: black;">办法</span>、字段和属性。</span></span><span style="color: black;"><strong style="color: blue;"><span style="color: black;">混淆</span></strong><span style="color: black;">:缩短类与成员的名<span style="color: black;">叫作</span>。</span></span><span style="color: black;"><strong style="color: blue;"><span style="color: black;">优化</span></strong><span style="color: black;">:指令级别的优化,合并重复指令、清理<span style="color: black;">没</span>用指令、<span style="color: black;">提高</span>指令执行效率。</span></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">4.2 R8</strong></p><span style="color: black;">AGP 3.3之后官方<span style="color: black;">起始</span><span style="color: black;">举荐</span><span style="color: black;">运用</span> R8,R8 与 ProGuard 不只是简单的替代关系,它还将脱糖、D8 整合到了<span style="color: black;">一块</span>,<span style="color: black;">极重</span>的<span style="color: black;">提高</span>了构建效率。</span><img src="https://mmbiz.qpic.cn/mmbiz_png/Ce6bSqXkduycvJHvwubnw1P5p4pIIlia2mmgFZLyahFChywNR9QK6GvkPw1oNOU4SMGXAOQh9Tws1u0ibWp6v4YQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;"><span style="color: black;"><span style="color: black;">图5 R8 处理对象及<span style="color: black;">功效</span>示意图</span><span style="color: black;"> </span></span><span style="color: black;">R8 基本兼容此前的 ProGuard 规则,但仍存在些许差异(applymapping、行号处理、Kotlin元数据处理、<span style="color: black;">没</span>用判定等)。R8 <span style="color: black;">再也不</span>高优<span style="color: black;">思虑</span>兼容性问题后,两者会派生出越来越多的<span style="color: black;">区别</span>点,<span style="color: black;">意见</span><span style="color: black;">定时</span>关注,博采众长。</span><span style="color: black;"><strong style="color: blue;">丨Jack & Jill</strong></span><span style="color: black;">小插曲:官方在2015年推行过一段时间的Jack & Jill<span style="color: black;">工具</span>,它<span style="color: black;">乃至</span>把javac<span style="color: black;">亦</span><span style="color: black;">包括</span>了进来,算是真正实现了端到端的编译。但Jack的性能与生态相比javac实在差距太大,官方出于成本<span style="color: black;">思虑</span>最后还是弃坑了。</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">4.3 AndResGuard</strong></p><span style="color: black;">AndResGuard 是<span style="color: black;">微X</span>推出资源优化<span style="color: black;">工具</span>。它的基本思想类似于 ProGuard 中的混淆,体积优化是它的附加收益,<span style="color: black;">同期</span>还<span style="color: black;">供给</span>了压缩、加密等选项。</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">4.4 ByteX</strong></p><span style="color: black;">ByteX 是字节开源的一套Java字节码插桩<span style="color: black;">工具</span>,<span style="color: black;">日前</span><span style="color: black;">重点</span><span style="color: black;">包含</span>优化与<span style="color: black;">检测</span>工作,其中<span style="color: black;">有些</span>子项<span style="color: black;">最后</span>会带来体积收益。<span style="color: black;">包含</span>R类内联、移除debug信息、access <span style="color: black;">办法</span>内联等。</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">4.5 Booster</strong></p><span style="color: black;">Booster 是滴滴开源的一套质量优化框架,其中<span style="color: black;">包含</span>体积优化专项,例如资源文件压缩、资源产物.ap_ 压缩、去冗余资源、R类内联、DataBinding BR内联等。</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">4.6 AGP</strong></p>
<h2 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;"><span style="color: black;">Android Gradle Plugin</span><span style="color: black;">(AGP)</span><span style="color: black;"><span style="color: black;">包括</span>了多个体积优化任务,<span style="color: black;">供给</span>了许多优化配置项,大部分任务<span style="color: black;">已然</span><span style="color: black;">做为</span>APK打包的标配。</span></span></h2><span style="color: black;"><span style="color: black;">通常</span>来讲,<span style="color: black;">咱们</span>的优化任务会依赖于这些任务的执行。<span style="color: black;">倘若</span>定制的优化<span style="color: black;">没</span>法兼容现存任务,则<span style="color: black;">必须</span>关闭或hook这些任务。接下来将<span style="color: black;">根据</span>编译<span style="color: black;">次序</span>简单介绍几个优化任务与配置:</span><span style="color: black;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">OptimizeResources</p>AGP4.2+ 新增的资源优化任务,<span style="color: black;">日前</span>只实现了资源文件路径的缩短,默认开启,可<span style="color: black;">经过</span> android.enableResourceOptimizations 关闭。
</span><span style="color: black;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">StripSymbols</p>NDK 会利用 llvm-strip 移除掉 native libraries 中的unneeded symbols,这部分优化工作<span style="color: black;">亦</span><span style="color: black;">能够</span>放在so编译<span style="color: black;">时期</span>完成。
</span><span style="color: black;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">MinifyWithR8/ProGuard</p>利用 R8 或 ProGuard 实现代码优化,此处就<span style="color: black;">再也不</span>赘述了。
</span><span style="color: black;"><span style="color: black;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">ShrinkResources</p>由 ShrinkResources 开关<span style="color: black;">掌控</span>,启用前提是<span style="color: black;">必要</span>开启 minifyEnable。其<span style="color: black;">功效</span>是将未被引用的资源文件替换为一个体积很小的格式文件
</span><span style="color: black;">(仍存在占位体积,<span style="color: black;">同期</span><span style="color: black;">保存</span>了该资源条目,<span style="color: black;">因此</span> resources.arsc 体积并不会减少)</span><span style="color: black;">,可<span style="color: black;">经过</span> res/raw/keep.xml 文件配置 shrinkMode 和白名单。</span></span><span style="color: black;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">PackageOptions</p>打包时选项,<span style="color: black;">包含</span>过滤 exclude、相同文件仅打包 pickFirst、<span style="color: black;">所有</span>打包 merge、so优化豁免 doNotStrip。
</span><span style="color: black;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Splits</p>分包/过滤策略,配置项<span style="color: black;">包含</span> ABI、资源配置(语言、分辨率等)。
</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">GEEK TALK</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><strong style="color: blue;">05</strong></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">百度APP优化项项概览</strong></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">5.1 Dex优化</strong></p><span style="color: black;"><span style="color: black;">百度APP 实现 Dex 的体积优化项<span style="color: black;">能够</span>分为两类:源码编译<span style="color: black;">时期</span>的优化;APK 打包<span style="color: black;">时期</span>对 Dex 文件的优化。两者的区别<span style="color: black;">重点</span>是优化对象<span style="color: black;">区别</span>,<span style="color: black;">因此</span>基于<span style="color: black;">区别</span>的优化<span style="color: black;">工具</span>实现,前者基于Java字节码<span style="color: black;">工具</span>实现</span><span style="color: black;">(如 ASM)</span><span style="color: black;">,后者基于 Dex 字节码<span style="color: black;">工具</span>实现</span><span style="color: black;">(如 Titan-Dex )</span><span style="color: black;">。</span></span><span style="color: black;"><strong style="color: blue;">丨Titan-Dex</strong></span><span style="color: black;">Titan-Dex 是百度开源的面向Android Dalvik(ART)字节码(bytecode)格式的<span style="color: black;">操作</span>框架,<span style="color: black;">能够</span>在二进制格式下实现修改已有的类,<span style="color: black;">或</span>动态生成新的类。百度Titan-hotfix<span style="color: black;">工具</span>即基于此框架实现。</span><span style="color: black;"><strong style="color: blue;"><span style="color: black;">R类优化</span></strong></span><span style="color: black;"> 工程组件越多,R类所占体积越大,未关闭资源依赖传递的<span style="color: black;">状况</span>下则更严重。<span style="color: black;">咱们</span>在编译期将代码中调用 R.type.name 的<span style="color: black;">地区</span><span style="color: black;">所有</span>替换<span style="color: black;">成为了</span>对应的id常量,<span style="color: black;">最后</span> R.class 会<span style="color: black;">做为</span><span style="color: black;">没</span>用类被 R8/ProGuard 清理掉。</span><span style="color: black;"><strong style="color: blue;">行号优化</strong></span><span style="color: black;"><span style="color: black;">Dex 中的 debug 区域占5~10%的<span style="color: black;">体积</span>,但其最大的<span style="color: black;">功效</span>是分析崩溃堆栈时定位。该区域<span style="color: black;">能够</span><span style="color: black;">经过</span>去除 ProGuard 规则</span><span style="color: black;">-keepattributes SourceFile,LineNumberTable </span><span style="color: black;">完全移除。<span style="color: black;">咱们</span><span style="color: black;">选取</span>在指令级别完成 debug infos 的映射与复用,<span style="color: black;">同期</span>联动百度性能平台</span><span style="color: black;">(<span style="color: black;">日前</span>仅供<span style="color: black;">机构</span>内部<span style="color: black;">运用</span>,功能可类比腾讯 bugly)</span><span style="color: black;">完成崩溃堆栈的还原,既优化了体积,又不会影响堆栈的分析。</span></span><span style="color: black;"><strong style="color: blue;"><span style="color: black;">注解优化</span></strong></span><span style="color: black;"><span style="color: black;"> Dex中注解分为三种类型:Build、Runtime、System。Build 和 Runtime对应 ProGuard 规则</span><span style="color: black;"> -keepattributes *Annotation*</span><span style="color: black;">,可优化的 System 注解<span style="color: black;">按照</span><span style="color: black;">详细</span>类型分别对应</span><span style="color: black;">-keepattributes InnerClasses, Signature, EnclosingMethod</span><span style="color: black;">。跟行号<span style="color: black;">同样</span>,<span style="color: black;">能够</span><span style="color: black;">经过</span>去除这些规则完成一刀切的优化。但<span style="color: black;">因为</span><span style="color: black;">咱们</span>接入的三方组件自带这些 ProGuard 规则,且部<span style="color: black;">归类</span>的 System 注解有<span style="color: black;">保存</span>的<span style="color: black;">必须</span>,<span style="color: black;">咱们</span><span style="color: black;">选取</span>后置地处理 Dex 文件,基于 Dex 字节码<span style="color: black;">工具</span>完成<span style="color: black;">目的</span>注解的移除。</span></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">5.2 资源优化</strong></p><span style="color: black;">资源优化的对象分为两类,一是资源<span style="color: black;">查找</span>表 resources.arsc,部分优化操作会<span style="color: black;">触及</span>到 res/ 及 R文件的修改,但本质都是从 resources.arsc 出发的;二是原始资源文件,<span style="color: black;">包含</span> res/和 assets/。</span><span style="color: black;"><span style="color: black;">介绍优化项前,<span style="color: black;">咱们</span>先看一张网上最经典的 resources.arsc 结构图</span><span style="color: black;">(<span style="color: black;">源自</span>CSDN社区)</span><span style="color: black;">:</span></span><img src="https://mmbiz.qpic.cn/mmbiz_png/Ce6bSqXkduycvJHvwubnw1P5p4pIIlia2tNkGUue4ibxIuRIHvwMGLb5QR2ibibxOEUB76sdQdwuZ93UDq77osPzgw/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;"><span style="color: black;">图6 resources.arsc 结构图</span><span style="color: black;"><strong style="color: blue;"><span style="color: black;">资源同名化</span></strong></span><span style="color: black;">在<span style="color: black;">实质</span>应用中,<span style="color: black;">咱们</span>默认<span style="color: black;">经过</span>资源 id <span style="color: black;">查询</span>资源内容,对资源名的<span style="color: black;">运用</span>频率<span style="color: black;">非常</span>低,仅限于<span style="color: black;">经过</span>资源名反查资源 id 以及 <span style="color: black;">经过</span>资源 id 获取资源名两种<span style="color: black;">状况</span>。<span style="color: black;">因此</span>资源项名<span style="color: black;">叫作</span>字符串池所占据的空间即是<span style="color: black;">咱们</span>的优化对象。极限优化结果是,这个池子里仅存放一个字符串,所有 ResTable_entry 的资源项名<span style="color: black;">叫作</span> index均指向这个池子里仅有的字符串,即所有资源的名字都变得<span style="color: black;">同样</span>了。<span style="color: black;">实质</span>场景中,<span style="color: black;">咱们</span>会有豁免和降级为混淆的需求,例如<span style="color: black;">经过</span>资源名反向<span style="color: black;">查找</span>资源id等<span style="color: black;">状况</span>。</span><span style="color: black;"><strong style="color: blue;"><span style="color: black;">资源文件路径优化</span></strong></span><span style="color: black;"><span style="color: black;">与 AndResGuard 中的资源路径混淆效果<span style="color: black;">类似</span>,都是尽可能缩短资源文件的路径长度,从而减少 ResTable_entry 的 value <span style="color: black;">体积</span>。<span style="color: black;">咱们</span>将路径 Hash 值转换到碰撞最少的位数,<span style="color: black;">做为</span><span style="color: black;">最后</span>的混淆结果,其优点在于混淆结果基本上是固定的,<span style="color: black;">没</span>需 applymapping。除此之外,<span style="color: black;">咱们</span>还较为激进地</span><span style="color: black;">去掉了大部分文件的后缀名。</span></span><span style="color: black;"><strong style="color: blue;"><span style="color: black;">资源配置优化</span></strong></span><span style="color: black;">从 arsc 中的资源 id <span style="color: black;">包括</span>了偏移量信息,系统<span style="color: black;">经过</span>偏移量在 arsc 中定位资源。<span style="color: black;">因此</span>图7中的空白区域<span style="color: black;">必要</span><span style="color: black;">保存</span>一个4字节的占位,以满足偏移量<span style="color: black;">查找</span>方式。<span style="color: black;">咱们</span>正在对此部分做优化,宗旨是<span style="color: black;">经过</span>优化不必要的 configuraion,达到减少对齐占位的目的。</span><img src="https://mmbiz.qpic.cn/mmbiz_png/Ce6bSqXkduycvJHvwubnw1P5p4pIIlia2A0Pph4HGJufYvPTkCOZuPeFxQ9Mvp6Tlh3NPIoOaKeuDHPia4MttO7g/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;"><span style="color: black;">图7 resources.arsc 空白占位示意图</span><span style="color: black;"><strong style="color: blue;"><span style="color: black;"><span style="color: black;">照片</span>压缩</span></strong></span><span style="color: black;"> <span style="color: black;">因为</span> webp 格式受限于 minsdkversion18,<span style="color: black;">咱们</span><span style="color: black;">日前</span>还是针对 png <span style="color: black;">照片</span>做压缩优化,<span style="color: black;">运用</span>的<span style="color: black;">工具</span><span style="color: black;">包含</span> TinyPng 和 ImageOptim。除了出图<span style="color: black;">周期</span>压缩外,<span style="color: black;">亦</span>会有后置流水线做压缩<span style="color: black;">检测</span>。</span><span style="color: black;"><strong style="color: blue;"><span style="color: black;"><span style="color: black;">没</span>用资源清理</span></strong></span><span style="color: black;">如4.5中<span style="color: black;">说到</span>的,ShrinkResources 并不会真正移除未被引用的资源文件。<span style="color: black;">不外</span><span style="color: black;">咱们</span><span style="color: black;">能够</span>拿到被 shrink 的 resources 列表,<span style="color: black;">而后</span>再利用资源优化<span style="color: black;">工具</span>做真正的删除。</span><span style="color: black;"><strong style="color: blue;">丨New ShrinkResource</strong></span><span style="color: black;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">2022.1发布的 AGPv7.1.0 更新了资源缩减功能,添加了实验性选项 android.experimental.enableNewResourceShrinker.preciseShrinking,该选项设置为true后 ShrinkResources 会完全移除未<span style="color: black;">运用</span>的文件资源及 value 资源,但 arsc 中仍会存在这些资源的填充占位。</p>
</span><span style="color: black;"><strong style="color: blue;"><span style="color: black;">arsc 压缩</span></strong></span><span style="color: black;">resources.arsc 的压缩体积收益很高,但对其进行压缩会影响<span style="color: black;">起步</span>速度和内存指标。<span style="color: black;">详细</span><span style="color: black;">原由</span>是:系统在加载 arsc 文件时,若 arsc 文件未压缩,可<span style="color: black;">运用</span> mmap 进行内存映射;若 arsc 文件被压缩了,则<span style="color: black;">必须</span>将其解压缩后读取到RAM 缓冲区,会<span style="color: black;">增多</span>内存<span style="color: black;">运用</span>,<span style="color: black;">亦</span>会拖慢<span style="color: black;">起步</span>速度。在业界大都压缩 arsc 的<span style="color: black;">状况</span>下,百度APP 出于综合考量<span style="color: black;">始终</span>未对 arsc 文件进行压缩。<span style="color: black;">没</span>独有偶,官方出于<span style="color: black;">一样</span>的<span style="color: black;">思虑</span>,从 Android11 <span style="color: black;">起始</span>强制<span style="color: black;">需求</span><strong style="color: blue;">resources.arsc 不可压缩且保持4位对齐</strong>,否则会直接安装失败。</span><img src="https://mmbiz.qpic.cn/mmbiz_png/Ce6bSqXkduycvJHvwubnw1P5p4pIIlia2e9jrtYGibicD3Wqg0BQRgAicF6XwTId2ichOKFwLlqLHycp5e5vQNgxxcQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;"><span style="color: black;">图8 Android11强调 resources.arsc 压缩对齐问题</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">5.3 ZIP优化</strong></p><span style="color: black;"><strong style="color: blue;"><span style="color: black;">压缩</span></strong></span><span style="color: black;"><span style="color: black;"> <span style="color: black;">日前</span><span style="color: black;">咱们</span><span style="color: black;">运用</span>的压缩算法有 7z 和 zopfli</span><span style="color: black;"></span><span style="color: black;">,后者压缩率和压缩耗时都有<span style="color: black;">显著</span><span style="color: black;">增多</span>,稳定性还在验证中。采用新的压缩算法时需<span style="color: black;">尤其</span><span style="color: black;">重视</span>两点,一是不要压缩 resources.arsc;二是<span style="color: black;">重视</span>压缩、 对齐、签名操作的<span style="color: black;">次序</span>。</span></span><span style="color: black;"><strong style="color: blue;"><span style="color: black;">文件路径优化</span></strong></span><span style="color: black;">如章节3.2 ZIP结构分析所示,APK 中有三处体积与文件路径长度<span style="color: black;">关联</span>:META-INF/、压缩源文件数据区的 local file header、中心目录区的 file header,资源文件路径优化效果<span style="color: black;">一样</span>会<span style="color: black;">表现</span>在<span style="color: black;">这儿</span>。同理<span style="color: black;">掌控</span> assets/ 下的文件路径<span style="color: black;">亦</span>可带来体积收益。</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">5.4 其他</strong></p><span style="color: black;"><strong style="color: blue;"><span style="color: black;">夜间模式优化</span></strong></span><span style="color: black;"><span style="color: black;">日前</span>百度APP的夜间资源是一个 APK 包,此前实现方式是与主包中的资源名保持一致,<span style="color: black;">经过</span>反射的<span style="color: black;">办法</span><span style="color: black;">查找</span>对应 id。现改为 id 一致,<span style="color: black;">这般</span>既避免了反射<span style="color: black;">查找</span>的耗时,章节 5.2中的资源优化<span style="color: black;">亦</span><span style="color: black;">能够</span>应用到资源 APK,进一步减小体积。</span><span style="color: black;"><strong style="color: blue;"><span style="color: black;">混淆规则</span></strong></span><span style="color: black;">ProGuard/R8 <span style="color: black;">供给</span>了多种多样的规则用以豁免代码优化操作,<span style="color: black;">倘若</span><span style="color: black;">运用</span><span style="color: black;">欠妥</span>可能会<span style="color: black;">导致</span>体积的白白浪费。<span style="color: black;">将来</span><span style="color: black;">咱们</span>计划制定一套<span style="color: black;">仔细</span>的 ProGuard 规则<span style="color: black;">运用</span>规范,并对<span style="color: black;">每一个</span>组件的 ProGuard 规则都进行校验,例如不<span style="color: black;">准许</span><span style="color: black;">显现</span>本组件包名范围外的 keep 规则、不<span style="color: black;">准许</span><span style="color: black;">显现</span>包级别 keep 等。</span><span style="color: black;"><strong style="color: blue;"><span style="color: black;">体积流水线</span></strong></span><span style="color: black;"><span style="color: black;">重点</span><span style="color: black;">包含</span>仓库体积约束流水线,二进制组件体积<span style="color: black;">检测</span>流水线,以及 APK <span style="color: black;">构成</span>体积分析流水线,分<span style="color: black;">周期</span>进行约束与分析。<span style="color: black;">日前</span>百度APP 建设了 APK 体积监控流水线,每当主线有代码合入、触发编译打包后,会即时对编译产物 APK 做体积分析,并与上一次编译产物进行比对,<span style="color: black;">能够</span>马上<span style="color: black;">发掘</span><span style="color: black;">反常</span>的体积增长。</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">GEEK TALK</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><strong style="color: blue;">06</strong></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">总结</strong></p><span style="color: black;">第五章介绍的优化项自21年8月至22年2月分批次上线,<span style="color: black;">时期</span>业务依旧在高速迭代,虽然有体积监控流水线<span style="color: black;">功效</span>,包体积仍会不可避免地<span style="color: black;">增多</span>。</span><span style="color: black;"><span style="color: black;">因为</span>优化机制<span style="color: black;">非常</span>底层,需进行充分的线下测试与线上小流量灰度,验证稳定性后<span style="color: black;">才可</span>正式上线。</span><span style="color: black;">上线/灰度前后百度APP 包体积<span style="color: black;">体积</span>对<span style="color: black;">例如</span>下:</span><span style="color: black;">优化项</span><span style="color: black;">优化前体积</span><span style="color: black;">优化后体积</span><span style="color: black;">Diff</span><span style="color: black;"><span style="color: black;">Dex 行号优化 & 混淆规则收敛 </span><span style="color: black;">(上线)</span></span><span style="color: black;">123.58MB</span><span style="color: black;">119.37MB</span><span style="color: black;">4.21MB</span><span style="color: black;"><span style="color: black;">资源名/路径优化 & 7z 压缩 & 夜间模式优化</span><span style="color: black;">(上线)</span></span><span style="color: black;">122.54MB</span><span style="color: black;">116.36MB</span><span style="color: black;">6.18MB</span><span style="color: black;"><span style="color: black;"><span style="color: black;">照片</span>压缩 & 热修插桩优化 </span><span style="color: black;">(上线)</span></span><span style="color: black;">117.07MB</span><span style="color: black;">116.00MB</span><span style="color: black;">1.07MB</span><span style="color: black;"><span style="color: black;">Dex 注解优化 </span><span style="color: black;">(灰度)</span></span><span style="color: black;">117.16MB</span><span style="color: black;">115.95MB</span><span style="color: black;">1.21MB</span><span style="color: black;"><span style="color: black;">启用R8 </span><span style="color: black;">(灰度)</span></span><span style="color: black;">119.06MB</span><span style="color: black;">116.62MB</span><span style="color: black;">2.44MB</span><span style="color: black;"><span style="color: black;">zopfli 压缩 & 资源缩减 & 资源配置优化</span><span style="color: black;">(灰度)</span></span><span style="color: black;">119.57MB</span><span style="color: black;">116.65MB</span><span style="color: black;">2.92MB</span><span style="color: black;">本文<span style="color: black;">重点</span>介绍了百度APP 包体积优化的基本思路,解构了优化对象,介绍了现有优化<span style="color: black;">工具</span>,最后简单介绍了百度APP <span style="color: black;">详细</span>实践的优化项及收益。后续<span style="color: black;">咱们</span>会针对<span style="color: black;">每一个</span>优化类型<span style="color: black;">仔细</span>介绍其原理与实现,<span style="color: black;">同期</span>逐步开源通用的体积优化<span style="color: black;">工具</span>,敬请期待。</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><strong style="color: blue;"> END</strong></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><strong style="color: blue;"><span style="color: black;">参考资料:</span></strong></span></p><span style="color: black;"><span style="color: black;"> 包<span style="color: black;">体积</span>与安装转化率 </span></span><span style="color: black;"><span style="color: black;">https://medium.com/googleplaydev/shrinking-apks-growing-installs-5d3fcba23ce2</span></span><span style="color: black;"><span style="color: black;"> ZIP格式 </span></span><span style="color: black;"><span style="color: black;">https://pkware.cachefly.net/webdocs/APPNOTE/APPNOTE-6.2.0.txt</span></span><span style="color: black;"><span style="color: black;"> ProGuard </span></span><span style="color: black;"><span style="color: black;">https://www.guardsquare.com/proguard</span></span><span style="color: black;"><span style="color: black;"> R8 </span></span><span style="color: black;"><span style="color: black;">https://r8.googlesource.com/r8</span></span><span style="color: black;"><span style="color: black;"> ProGuard与R8对比 </span></span><span style="color: black;"><span style="color: black;">https://www.guardsquare.com/blog/proguard-and-r8</span></span><span style="color: black;"><span style="color: black;"> AndResGuard </span></span><span style="color: black;"><span style="color: black;">https://github.com/shwenzhang/AndResGuard</span></span><span style="color: black;"><span style="color: black;"> ByteX </span></span><span style="color: black;"><span style="color: black;">https://github.com/bytedance/ByteX</span></span><span style="color: black;"><span style="color: black;"> Booster </span></span><span style="color: black;"><span style="color: black;">https://github.com/didi/booster</span></span><span style="color: black;"><span style="color: black;"> AGP </span></span><span style="color: black;"><span style="color: black;">https://developer.android.com/studio/releases/gradle-plugin</span></span><span style="color: black;"><span style="color: black;"> Titan-Dex </span></span><span style="color: black;"><span style="color: black;">https://github.com/baidu/titan-dex</span></span><span style="color: black;"><span style="color: black;"> zopfli </span></span><span style="color: black;">https://en.wikipedia.org/wiki/Zopfli</span><span style="color: black;"><span style="color: black;">举荐</span>阅读:</span>
<h1 style="color: black; text-align: left; margin-bottom: 10px;"><a style="color: black;"><span style="color: black;">百度APP iOS端内存优化实践-大块内存监控<span style="color: black;">方法</span></span></a></h1>
<h1 style="color: black; text-align: left; margin-bottom: 10px;"><a style="color: black;"><span style="color: black;">百家号基于AE的视频渲染技术探索</span></a></h1>
<h1 style="color: black; text-align: left; margin-bottom: 10px;"><a style="color: black;"><span style="color: black;">百度工程师教你玩转设计模式(观察者模式)</span></a></h1>
<h1 style="color: black; text-align: left; margin-bottom: 10px;"><a style="color: black;"><span style="color: black;">Linux透明大页机制在云上大规模集群实践介绍</span></a></h1>
<h1 style="color: black; text-align: left; margin-bottom: 10px;"><a style="color: black;"><span style="color: black;">超<span style="color: black;">有效</span>!Swagger-Yapi的<span style="color: black;">奥密</span></span></a></h1>
<h1 style="color: black; text-align: left; margin-bottom: 10px;"><a style="color: black;"><span style="color: black;">百度直播iOS SDK平</span></a>台化输出改造</h1><img src="data:image/svg+xml,%3C%3Fxml version=1.0 encoding=UTF-8%3F%3E%3Csvg width=1px height=1px viewBox=0 0 1 1 version=1.1 xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink%3E%3Ctitle%3E%3C/title%3E%3Cg stroke=none stroke-width=1 fill=none fill-rule=evenodd fill-opacity=0%3E%3Cg transform=translate(-249.000000, -126.000000) fill=%23FFFFFF%3E%3Crect x=249 y=126 width=1 height=1%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E" style="width: 50%; margin-bottom: 20px;"><span style="color: black;"><span style="color: black;">一键三连,好运连连,bug不见</span><span style="color: black;">
页:
[1]