qq红包接龙最佳秘诀
扫描关注qq红包接龙最佳秘诀

手机扫描二维码

支付宝应用结构的优化:包装尺寸的极度压缩

qq红包接龙最佳秘诀2019-11-21KN5O3J 5524

原创标题:支付宝应用结构优化:包装尺寸极度压缩

作者:琉球|资料来源:公共号码海洋保护区

1

前言

在本章中,我们将围绕“支付宝应用构建优化分析”展开一个新系列。我们将在“代码管理证书管理版本管理建筑包装的维度中讨论细分和拆解客户的具体实施方案,并引导大家进一步了解支付宝在应用构建模块下的持续优化。

本节将主要记录通过压缩支付宝安卓包的大小来提高运营效率和质量。

2

背景

没有必要多说包装尺寸的重要性。软件包大小直接影响用户的下载和保留,甚至一些制造商的安装前强制性要求也必须小于某个值。然而,随着业务的迭代开发,应用程序将变得越来越大,安装包将继续扩展。因此,缩减包大小是一个长期和持续的治理过程。

3

方案介绍

支付宝在包装尺寸的优化上一直朝着这个方向努力,所以我们引入了很多方案,比如“proguard Code混淆”、“图片从png到tinypng到webp”、“引入7zip压缩方案”等。该方案不同于上述传统方案。它直接删除dex中无用的信息,达到即时缩小支付宝包大小210万的目的,而不影响整个操作逻辑和性能,甚至减少一点操作内存。

导言:

导言:

在进入细节之前,我需要谈一下整个Java系统的调试逻辑。JVM使用运行。类文件已加载。Android发明了dalvik和art虚拟机,以使包更紧凑,运行效率更高。两个虚拟机都运行。dex文件(当然,art虚拟机也可以同时运行oat文件,这超出了本文的范围)。因此,dex文件中的信息内容与类文件中包含的信息完全相同。不同之处在于dex文件消除了类中的信息。一个索引包含许多类文件,并且在结构上有很大差异。类是一个流结构,dex是一个分区结构,每个块都是按偏移量索引的。后面只会提到dex结构,而不是类结构。dex的结构可以由下图表示:

展开全文

dex文件的结构实际上非常清晰,分为几个大块,标题区,索引区,数据区和地图区。该优化方案优化并删除数据区中的调试区。

debugItem 干吗用?

首先,您需要知道debugItem中存储了什么。它主要包含两种信息:

上图是一个相对常见的碰撞信息。红色框中的行号是通过查找这个调试对象获得的。

debugItem 有多大?

在支付宝场景中,调试包为4-5M,发布包约为350万,约占dex文件大小的5.5%,这与谷歌的官方数据一致。如果这部分可以直接拆下来,是否很有吸引力?

debugItem 能直接去掉吗?

显然不是,如果它被移除,那么所有报告的碰撞信息都将没有行号,所有的行号都将变成-1,并且它将被喷洒并且找不到北方。事实上,有一个配置是当proguard可以删除或保留这个行号信息时,-保留源文件,linenumbertable就是这个角色,为了便于问题的定位,基本上所有的开发都保留了这个配置。因此,该方案的核心思想是删除debugItem,同时允许崩溃在报告时获得正确的行号。至于集成开发环境调试,这是一个更好的解决方案。我们只需要处理发布包,而不是调试包。

4

一个方案

核心思想也相对简单,也就是线号搜索离线,这样原本存储在应用程序中的线号对应关系就可以提前取出并存储在服务器中。崩溃报告时,可以通过拉出的行号表提前反转行号,解决崩溃信息报告没有行号、无法定位的问题。虽然思路很简单,但实施仍然有点复杂,上网的推动力相当曲折。经过几次调整后,总计划可以抽象为下图:

如上所示,有四个核心点:

上述方案花了大约两周的时间来展示整个演示,其他几个修改点不是很难,但困难在于报告指令集编号。我们知道所有崩溃最终都会有一个可抛出的对象,它保存着整个堆栈信息。在阅读源代码并反复尝试之后,我们发现我想要的指令集行号实际上在这个对象中。可以用下面一个简单的图形示意:

在打印崩溃堆栈信息之前,每个throwable都会调用art虚拟机提供的jni方法,并返回一个名为stackTrace的内部对象,以保存在Throwable对象中。stackTrace对象保存整个方法的调用堆栈,当然包括指令集行号。当以后获得实际的堆栈信息时,将再次调用art的jni方法,stackTrace方法将被丢弃。底层将通过stackTrace对象中的指令集行号反转正式的源文件行号。其实很简单。反射以获得这个可抛出的堆栈跟踪对象,获得指令集行号,然后报告它。这里要注意的一点是令人厌恶的。每个虚拟机的实现是不同的。首先,内部对象的名称是stackTrace,有些是仰面。那么内部对象的类型也是非常多种多样的。有些是int数组,有些是long数组,有些是object数组。但是,它们都有这个指令集行号。对于不同版本的虚拟机,需要使用不同的方法来解析该对象。它可能与4个虚拟机兼容,4.x、5.x、6.x、7.x、7.x。虚拟机统一后。

5

备选方案2

上述方案实际上相当完美,不存在兼容性问题。删除是直接使用proguard在java层获得指令集行号,而不需要任何挂钩。如果只需要处理崩溃报告,方案1就足够了,但是支付宝中有很多场景远远不够。例如:

性能,CPU,内存异常时调用栈。 native crash 时的 Java 调用栈。

上述情况都涉及堆栈信息。在方案1中,throwable中的stackTrace内部对象由反射调用,根本无法处理,因此需要不同的方法。第一个想法是尝试挂钩艺术虚拟机,每天查看源代码,看看可以挂钩的地方。最后,我放弃了。一个是担心兼容性,另一个是钩子上有太多的点,这让我很恐慌。最后,我改变了想法,试图直接修改dex文件,保留一个小的debugItem,这样当系统寻找行号时,指令集行号和源文件行号是一致的,所以不需要做任何事情。监控报告的任何行号都直接更改为指令集行号,并且只需要修改dex文件。可由以下示意图表示:

如上图所示:最初每个方法都有一个debugInfoItem,每个debuginfoItem都有指令集行号和源文件行号之间的映射关系。我的修改实际上非常简单,也就是说,所有冗余的debugInfoItem都将被删除,只留下一个debugInfoItem。所有方法都指向同一个DebugginFoitem,这个DebugginFoitem中的指令集行号与源文件行号一致,所以不管用什么方法检查行号,都会得到指令集行号。其中,许多坑被踩过。事实上,只留下一个调试信息是不够的。为了与所有虚拟机的搜索方法兼容,有必要对debugInfoItem进行分区。此外,debugInfoItem表不能太大。当遇到一个凹坑时,当在androidO上执行dex2oat优化时,它将频繁地遍历这个debugInfoItem,导致AOT编译缓慢,这最终通过对debugInfoItem进行分区来解决。这个计划相当彻底,没有必要改变proguard或hook native。然而,如果只需要处理崩溃的行号问题,它仍然是第一选择。该选项略有更改。在早期阶段,dex的文件结构每天都被研究,每个细节都被提取出来,只有当有更大程度的确定性时,它才能被改变。

6

摘要

目前,该计划已在支付宝正式推出。经过几轮测试,它仍然相对稳定。支付宝的整体包装尺寸减少了约210万英镑,而实际的dex尺寸减少了约350万英镑..

通过这一部分的内容,我们对支付宝通过不断缩小安卓客户端上的包大小所积累的思想和实践有了初步的了解。由于空间限制,我们无法实现所有的技术要点。而相应的技术核心,我们也应用于海洋保护区并出口到外部世界,欢迎大家开始体验:

https://tech.antfin.com/docs/2/49549

我也期待您对安卓终端包大小压缩的设计思想和具体实践的反馈。欢迎大家一起讨论和交流。

-

-结束-

最后,我想推荐我的独立博客:http://liuwangshu.cn/

它包含了安卓领域罕见的原创知识系统,所有文章都是原创的!

最后,我想推荐我的独立博客:http://liuwangshu.cn/

它包含了安卓领域罕见的原创知识系统,所有文章都是原创的!

如果你喜欢我的文章,请在公共号码““后场村编码”上加一个星号,以便阅读。回到搜狐看更多

负责任的编辑:

发表评论