移动App性能测评与优化1.4.2 smaps

1.4.2 smaps

由于Android底层基于Linux内核,进程内存信息也和Linux一致,所以Dalvik Heap之外的信息都能够从/proc/<pid>/smaps中取得。

在smaps中,列出了进程的各个内存区域,并根据分配的不同用途做标识,以下是root用户使用cat
/proc/<pid>/smaps的一个例子:

788c2000-789bf000
rw-p 00000000 00:00 0         
[stack:5113]

Size:               1012 kB

Rss:                   4 kB

Pss:                   4 kB

Shared_Clean:          0 kB

Shared_Dirty:          0 kB

Private_Clean:         0 kB

Private_Dirty:         4 kB

Referenced:            4 kB

Anonymous:             4 kB

AnonHugePages:         0 kB

Swap:                  0 kB

KernelPageSize:        4 kB

MMUPageSize:           4 kB

Locked:                0 kB

VmFlags: rd wr
mr mw me nr

dumpsys统计各个内存块的Pss、Shared_Dirty、Private_Dirty等值,并按以下原则进行了归并:

/dev/ashmem/dalvik-heap和/dev/ashmem/dalvik-zygote归为Dalvik Heap。

其他以/dev/ashmem/dalvik-开头的内存区域归为Dalvik Other。

Ashmem对应/dev/ashmem/下所有不以dalvik-开头的内存区域。

Other dev对应的是以/dev下其他的内存区域。

文件的mmap按已知的几个扩展名分类,其余的归为Other
Mmap。

其他部分,如[stack]、[malloc]、Unknown等。

了解了dumpsys的方法后,我们可以自己解析smaps,看看归并前各项的内存都是多少。这样能够得到比dumpsys更详细的信息,有助于分析一些问题。

首先将Pss分为以下几大类,计算各部分占比。在这个例子里,几大项是三分天下的节奏。Dalvik和Other dev内存都占了30%以上,剩下的是mmap和Unknown。进行内存优化时不能只看Dalvik部分,需要同时评估所有的部分。

1. Dalvik

Dalvik内存分为多个区域,meminfo统计的是所有区域累加的值:

Dalvik_Heap      5529

 +                             
/dev/ashmem/dalvik-heap (deleted)  
4680

 +                           
/dev/ashmem/dalvik-zygote (deleted)   
849

Dalvik_Other     3240

*
LinearAlloc    1229

*
Accounting     1579

*
Code_Cache     432

 +                      
/dev/ashmem/dalvik-LinearAlloc (deleted)   1229

 +                    
/dev/ashmem/dalvik-aux-structure (deleted)   1291

 +                         
/dev/ashmem/dalvik-bitmap-2 (deleted)   
192

 +                        /dev/ashmem/dalvik-card-table
(deleted)     96

 +                   
/dev/ashmem/dalvik-jit-code-cache (deleted)    432

其中:

Dalvik_Heap—包括dalvik-heap和dalvik-zygote。堆内存,所有的Java对象实例都放在这里。

LinearAlloc—包括dalvik-LinearAlloc。线性分配器,虚拟机存放载入类的函数信息,随着dex里的函数数量而增加。著名的65535个函数的限制就是从这里来的。

Accounting—包括dalvik-aux-structure、dalvik-bitmap、dalvik-card-table。这部分内存主要做标记和指针表使用。dalvik-aux-structure随着类及方法数目而增大,dalvik-bitmap随着dalvik-heap的      增大而增大。

Code_Cache—包括dalvik-jit-code-cache。jit编译代码后的缓存,随着代码复杂度的增加变大。

由于堆内存部分往往是应用消耗内存最多的地方,在内存优化中,最常见的方法就是减少Dalvik Heap中创建的对象,能够直接减少Dalvik Heap,并间接减少Accounting部分。减少代码会直接减少运行辅助部分。

在进行不同版本的对比测试时,我们往往会发现Dalvik Other和Dex Mmap出现了稳定的增长,这是由新加入的代码引入的内存消耗。

根据Dalvik虚拟机的原理,在加载class时,会根据类的变量个数及函数个数申请相应大小的内存,作为运行时的内部指针。这部分内存就会体现在LinearAlloc及aux-structure的增长中。随着版本的开发,应用class的数目及复杂度也在不断地增长,因此Dalvik
Other部分也在不断地增长。

由于这部分内存的增长取决于代码复杂度,因此通常情况下并没有简单直接的方法能够降低它们的消耗。但是通过仔细分析它们的组成及原理,还是能够找出一些间接的方法降低这部分内存的,详细方法请见2.6节。

2. mmap

系统会将一些文件mmap到内存中,对各个文件进行mmap的时机及大小比较复杂。dex_mmap是其中主要的内容:

apk_mmap         648

dex_mmap         1448

 +    /data/dalvik-cache/data@app@com.example-2.apk@classes.dex      917

 +                                          
/system/app/Stk.odex     16

 +                            
/system/app/TelephonyProvider.odex   
140

 +                          /system/framework/android.policy.odex      8

 +                           
/system/framework/bouncycastle.odex     
2

 +                              
/system/framework/conscrypt.odex     
3

 +                                   
/system/framework/core.odex     50

 +                                     /system/framework/ext.odex     19

 +                              
/system/framework/framework.odex   
249

 +                             
/system/framework/framework2.odex    
44

jar_mmap         4

ttf_mmap         47

so_mmap          3127

other_mmap       11

应用的dex会占据较大的空间,并且随着代码增加使得dex文件变大,占用的内存也会增加。减小dex的(相当于减少代码)尺寸能够降低这部分内存占用,同时也会减少dalvik部分的内存。

时间: 2024-10-11 21:44:18

移动App性能测评与优化1.4.2 smaps的相关文章

移动App性能测评与优化导读

前 言 Preface 写作背景 当前移动设备越来越多地涌现在我们日常生活中,像网络购物.充值缴费.新闻资讯.理财.团购.车辆保养等都可以通过移动设备来搞定.通过移动设备可以帮助人们更便捷高效地完成很多事,同时越来越多的需求也希望能通过移动设备来完成,这样也催生了很多工作机会,让IT技术人员能开发更多的App来满足不同用户的不同需求.相对于传统PC,移动设备有其自身的特点,如屏幕小.移动网络复杂且需要收费.电量有限等.因此,在完成用户一系列需求的背后,我们也面临一系列的问题.比如说,如何能保证开

移动App性能测评与优化2.1.2 软件测试

2.1.2 软件测试 上面一节讲述的都是从整机层面去量化并控制手机功耗,相比做App的公司来说做手机ROM的厂商较少.那么从应用的性能优化出发,上面讲述的硬件测试方法就不那么实用了,原因如下: 每个App本身的耗电是微量的,硬件测试方法中仪器本身波动可能无法体现App的功耗: 硬件测试方法只能通过测试整机功耗来体现App耗电,而这样很难避免其他App影响测试结果. 为了解决这个问题,MIG专项测试组从分析Android系统电量统计原理入手,并结合在实际项目中对耗电优化做的工作,来分享下对App功

移动App性能测评与优化1.3.2 问题所在

1.3.2 问题所在 在了解DVM分配释放内存的机制后,根据dumpsys观察到的现象,猜测可能出现了页利用率问题(页内碎片).如图1-13所示,第一行:在开始阶段,内存分配较满.第二行:经过GC(垃圾回收)后,大部分对象被释放,少部分留下来.   图1-13 产生内存碎片 这种情况下可能会产生的问题是,整页的4KB内存中可能只有一个小对象,但统计PrivateDirty/Pss时还是按4KB计算. 在通常的JVM中,借助Compacting GC机制,整理内存对象,将散布的内存移动到一起.但根

移动App性能测评与优化1.6 本章小结

1.6 本章小结 在这一章里,我们通过对几个案例的分析,基本了解了Android应用的各种内存组成,以及这些成分是如何被消耗的,也总结出了一些节约和优化内存的经验.在这一小节里我们把经验都列出来供读者参考. 内存的主要组成索引: Native Heap:Native代码分配的内存,虚拟机和Android框架本身也会分配 Dalvik Heap:Java代码分配的对象 Dalvik Other:类的数据结构和索引 so mmap:Native代码和常量 dex mmap:Java代码和常量 内存工

移动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      

移动App性能测评与优化1.5 案例:优化dex相关内存

1.5 案例:优化dex相关内存 上一节提到,随着代码功能的增加,代码复杂度也在不断地变大,这时我们往往会发现Dalvik Other和Dex Mmap这两部分消耗的内存也在不断增加.在之前的例子里,我们知道这两部分的内存已经接近总内存的一半.在Dalvik Heap已经充分优化的情况下,我们有必要继续研究这部分内存如何优化. 我们已经知道Dalvik Other存放的是类的数据结构及关系,而Dex Mmap是类函数的代码和常量.通常情况下,要减少这部分内存,需要从代码出发,精简无用代码,或者将

移动App性能测评与优化2.1.1 硬件测试

2.1.1 硬件测试 方法1:通过Android API获取,代码如下: registerReceiver(receiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)): 这种方法的缺点:获取手机整机耗电,实时性差精度小(只能监控电池电量剩余量和跳变),测试工具本身的性能消耗,手机休眠后无法持续监测. 方法2:通过读取系统电池传感器设备节点. /sys/class/power_supply/battery/uevent 这种方法的缺点是:测

移动App性能测评与优化1.2.1 测试流程

1.2.1 测试流程 由于内存测试属于性能测试,Android系统又和Linux有很多相通之处,因此我们可以参考常见的Linux性能测试方法和指标,来制定客户端性能测试方案.常见的测试方法包括Monkey/UIAutomator类的常规压力测试.大数据/操作的峰值压力测试.长时间运行的稳定性测试等.这些方法都可以叠加在内存测试的方案中,观察这类场景下的应用内存情况,经常能够发现类似内存泄漏或OOM的问题. 参考了常见性能测试的方案,以及总结了以往对内存性能测试的经验后,我们总结出了一套进行内存测

移动App性能测评与优化1.4.1 从物理内存到应用

1.4.1 从物理内存到应用 我们首先要了解系统的内存机制,搞清楚物理内存是如何被分配到各个进程的,以及共享内存的机制,等等,理解这些机制对测试及优化都会有很大帮助. 根据Google提供的Android整体架构图,如图1-17所示,可以看到Android系统是基于Linux内核的,因此底层的内存分配及共享机制与Linux基本相同.但由于Android是为移动设备设计的,所以整套架构为了符合移动设备的特性,需要有较低的内存及能耗需求.因此Android只使用了Linux内核,不使用传统Linux