移动App性能测评与优化1.5.4 dex文件优化

简介:

1.5.4 dex文件优化

为了达到优化的目的,我们需要先了解dex文件的结构。dex文件结构如表1-2所示。

表1-2 dex文件结构

区 域  描 述  内 容

Header            

索引区  String Id list 指向Data的偏移量  

      Type Id list      

      Method Prototype Id list      

      Field Id list       

      Method Id list         

      Class Definition list        

Data区 ClassData    类数据  常量及变量定义Id

                 接口Id

                 成员函数Prototype Id

                 类Annotation的偏移量

      StringData   字符串数据  类名

                 Proto字符串

                 常量字符串

      Code    函数代码     Dalvik字节码

                 函数Debuginfo的偏移量

                 函数Annotations的偏移量

      StaticValues 静态变量初始值

      Debuginfo   Debug信息 

      Annotation  Annotations

      Map list     

 

简而言之,为了节约空间,dex将原先在各个class文件中重复的信息集中放置在一起,并以索引和指针的形式支持快速访问。虚拟机能够通过索引表在Data区域中找到需要的信息。

下面我们看一个访问字符串的例子。在dex文件结构中,读取字符串需要先到StringIdList中查表,然后根据查到的地址到Data区读取内容。StringIdList的数据结构如下:

struct DexStringId {

  u4 stringDataOff;

};

现在我们模拟虚拟机读取一个字符串,来观察内存的消耗。假设有一个字符串的id = 6728,对应的地址就会是112 + 6728 = 6990。因此虚拟机首先根据string ID读取0x006990 - 0x006994的内容,此时系统会加载0x006000~0x006fff的整页内存,从Pss角度来看,会增加4KB。

虚拟机读到的内容是stringDataOff = 0x531ed4,随后虚拟机会继续从0x531ed4读取字符串内容,假设字符串长度是45字节,则虚拟机会读取0x531ed4~0x531f04的内容,但此时系统也必须加载0x531000~0x531fff的整页内存,从Pss角度来看,会再次增加4KB。

由此可见,在有些情况下,虚拟机读取data区的一个数据,就至少要消耗8KB物理内存。如果多次读取的分散在文件各处的数据,就可能会以4KB的倍数快速消耗内存。

Android SDK提供了dexdump工具来观察dex文件内容,我们以此工具来看看dex的数据内容:

dexdump classes.dex

Processing 'classes.dex'...

Opened 'classes.dex', DEX version '035'

Class #0 header:

...

Class #0            -

  Class descriptor  : 'Laaa/aaa;'

...

Class #1            -

  Class descriptor  : 'Laaa/bbb;'

...

Class #2            -

  Class descriptor  : 'Lbbb/ccc;'

...

根据对dex数据的观察,我们发现dex文件中数据基本是按类名的字母顺序进行排列的,这样同样包名的类会排在一起。但在实际程序执行中,同一个package下的类并不会全部一起调用,而是和很多其他package下的类进行交互,但mmap加载了整个页面,可能会有很多无用数据。为了减少这样的情况,我们在生成文件时要尽量将使用到的数据内容排布在一起。在APK的编译流程中,Proguard混淆工具正好是能够对类名进行修改的,可以根据程序运行的逻辑,将那些会互相调用的类改为同一个package名,这样就可以使它们的数据排布在一起。

以上表数据为例,Class的排列顺序是aaa/aaa、aaa/bbb、bbb/ccc。假设我们的应用运行逻辑是aaa/aaa、bbb/ccc,而aaa/bbb在某些特殊时候才能用到。但在当前的排列情况下,加载了aaa/aaa和bbb/ccc就必然要加载aaa/bbb。我们可以用Proguard等工具来控制类名,将aaa/bbb等不常用的类放在后面,则aaa/bbb平时就不会加载。如下所示:

dexdump classes.dex

Processing 'classes.dex'...

Opened 'classes.dex', DEX version '035'

Class #0 header:

...

Class #0            -

  Class descriptor  : 'La0;' # 原aaa/aaa

...

Class #1            -

  Class descriptor  : 'La1;' # 原bbb/ccc

...

Class #2            -

  Class descriptor  : 'La2;' # ...

...

Class #100            -

  Class descriptor  : 'La100;' # 平时用不到的aaa/bbb

...

经验总结

根据上述的流程,我们探讨了Dalvik Other和.dex mmap部分的内存,大致搞清楚了它们被消耗的机制,以及一些能够减少消耗的方法。经验如下:

在优化内存时,不只有堆内存,还有其他许多类型的内存能够进行分析和优化。

dex文件有很多优化空间。在仔细统计并调整了dex文件的顺序后,往往能够节约1MB以上的mmap内存。

引入SDK库和调用新的系统API时需要考虑成本。有可能一些不常用的功能会导致大量的内存消耗。这时有可能需要多进程方案,将这些影响内存的操作放入临时进程执行。

相关文章
|
30天前
|
移动开发 开发框架 小程序
uni-app:demo&媒体文件&配置全局的变量(三)
uni-app 是一个使用 Vue.js 构建多平台应用的框架,支持微信小程序、支付宝小程序、H5 和 App 等平台。本文档介绍了 uni-app 的基本用法,包括登录示例、媒体文件处理、全局变量配置和 Vuex 状态管理的实现。通过这些示例,开发者可以快速上手并高效开发多平台应用。
|
1天前
|
数据采集 网络协议 算法
移动端弱网优化专题(十四):携程APP移动网络优化实践(弱网识别篇)
本文从方案设计、代码开发到技术落地,详尽的分享了携程在移动端弱网识别方面的实践经验,如果你也有类似需求,这篇文章会是一个不错的实操指南。
11 1
|
29天前
|
Linux 开发工具 数据安全/隐私保护
linux异常一:feng 不在 sudoers 文件中,此事将被报告。yum提示Another app is currently holding the yum lock; waiting for
这篇文章介绍了在CentOS 7系统中安装Docker时遇到的两个常见问题及其解决方法:用户不在sudoers文件中导致权限不足,以及yum被锁定的问题。
37 2
linux异常一:feng 不在 sudoers 文件中,此事将被报告。yum提示Another app is currently holding the yum lock; waiting for
|
3月前
|
JSON Linux 网络安全
【Azure 应用服务】如何从App Service for Linux 的环境中下载Container中非Home目录下的文件呢?
【Azure 应用服务】如何从App Service for Linux 的环境中下载Container中非Home目录下的文件呢?
|
3月前
|
Java Windows 容器
【应用服务 App Service】快速获取DUMP文件(App Service for Windows(.NET/.NET Core))
【应用服务 App Service】快速获取DUMP文件(App Service for Windows(.NET/.NET Core))
|
3月前
|
API 网络架构
【Azure Logic App】在中国区的微软云服务上,使用逻辑应用是否可以下载SharePoint上的文件呢?
【Azure Logic App】在中国区的微软云服务上,使用逻辑应用是否可以下载SharePoint上的文件呢?
【Azure Logic App】在中国区的微软云服务上,使用逻辑应用是否可以下载SharePoint上的文件呢?
|
3月前
|
Java Go Windows
【应用服务 App Service】App Service中上传文件/图片(> 2M)后就出现500错误(Maximum request length exceeded).
【应用服务 App Service】App Service中上传文件/图片(> 2M)后就出现500错误(Maximum request length exceeded).
|
3月前
|
开发框架 缓存 .NET
【App Service】在Azure App Service中分析.NET应用程序的性能的好帮手(Review Stack Traces)
【App Service】在Azure App Service中分析.NET应用程序的性能的好帮手(Review Stack Traces)
|
3月前
|
存储 开发框架 监控
【Azure Logic App】添加 Storage Account 来提升 Logic App 的性能
【Azure Logic App】添加 Storage Account 来提升 Logic App 的性能
|
3月前
|
前端开发 JavaScript Linux
【Azure 应用服务】在Azure App Service for Linux环境中,部署的Django应用,出现加载css、js等静态资源文件失败
【Azure 应用服务】在Azure App Service for Linux环境中,部署的Django应用,出现加载css、js等静态资源文件失败

热门文章

最新文章

下一篇
无影云桌面