- 内存管理
- 内存泄漏
- 内存使用查看方法
- 关于内存测试项 自动化工具
1、 Android中的进程
Native进程
用C/C++编写的,不包含dalvik实例的进程,/system/bin/目录下面的程序文件运行后都是以native进程形式存在的。/system/bin/surfaceflinger、/system/bin/rild、procrank等就是native进程。 内存函数包括 MALLOC/FREE,NEW/DELETE等。动态内存需要人工管理。
Dalvik进程
- Android中运行于dalvik虚拟机之上的进程,进程中存在一个虚拟机实例
- dalvik虚拟机的宿主进程由fork()系统调用创建
- 一般应用开发者管辖之内的内存空间
- 每一个java进程都是存在于一个native进程中
- java机制下的一些内存管理 例如:GC
1.1、进程的地址空间
在32位操作系统中,进程的地址空间为0到4GB,程序布局如下示意图:
这里主要说明一下Stack和Heap: Stack空间(进栈和出栈)由操作系统控制,其中主要存储函数地址、函数参数、局部变量等等,所以Stack空间不需要很大,一般为几MB大小。 Heap空间由程序控制,程序员可以使用malloc、new、free、delete等函数调用来操作这片地址空间。Heap为程序完成各种复杂任务提供内存空间,所以空间比较大,一般为几百MB到几GB。正是因为Heap空间由程序员管理,所以容易出现使用不当导致严重问题。
1.2、进程内存空间和RAM之间的关系
虚拟内存(Virtual Memory):利用磁盘空间虚拟出的一块逻辑内存。(地址空间)
物理内存(Physical Memory):真实物理内存所能表达的地址空间范围(物理空间)
一个页被多个虚拟地址引用,并且是不可修改部分, Sharaed_Clean
一个页被多个虚拟地址引用,并且是被修改过的部分,Sharaed_Dirty
一个页只被当前进程的虚拟地址引用,并且是不可修改部分,Private_Clean
一个页只被当前进程的虚拟地址引用,并且是被修改过的部分,Private_Dirty
VSS: Virtual Set Size = Size
PSS: Proportional Set Size = (Shared_Clean + Shared_Dirty) / Num_of_shared_process + Private_Dirty +Private_Clean
RSS: Resident Set Size = Shared_Clean+Shared_Dirty+Private_Clean+Private_Dirty
USS: Unique Set Size = Private_Clean + Private_Dirty
一般来说内存占用大小有如下规律:VSS >= RSS >= PSS >= USS
RAM作为进程运行不可或缺的资源,对Android系统性能和稳定性有着决定性影响,RAM的一部分被操作系统留作他用,比如显存等等,当然这个程序员无法干预,我们也不必过多地关注它。进程空间中的heap空间是我们需要重点关注的。heap空间完全由程序员控制,我们使用的malloc、C++ new和java new所申请的空间都是heap空间, C/C++申请的内存空间在native heap中,而java申请的内存空间则在dalvik heap中。
2、Android中的内存泄漏
Native层
Java层
2.1、查看内存使用情况的若干方法
1〉 adb shell dumpsys meminfo
Total RAM: 2843728 kB (status normal)
Free RAM: 1768733 kB (272373 cached pss + 1252952 cached kernel +
55524 free + 83736 ion cached + 104148 gpu cached)
Used RAM: 977510 kB (737470 used pss + 205116 kernel + 56 trace buffer + 34868 ion disp)
Lost RAM: 97485 kB
- ToTal RAM 手机总内存
- Free RAM 为剩余内存(其中cached pss为后台缓冲进程,当系统内存不足或缓冲进程数目达到系统限制最大数时会杀掉(部分)以释放内存。cached为高速缓冲存储器的内存,这部分内存已经分配好了,但是系统为了节约频繁申请内存开销,free时会把一部分内存cache起来,当用户再次申请内存时可能会直接从缓冲拿一块出来。free为未分配的物理内存)
- Used RAM 为用户态使用总内存; Lost RAM 为内核态使用内存(比如OpenGL纹理内存、GPU占用内存、图形显示ION buffer都包含在Lost RAM里)
- 当Free RAM比较小时可以认为系统内存不足(有种情况不能确定就是:Lost RAM占用内存很大,Lost RAM可能是内核缓冲内存太多了导致Free RAM小,但是并不是内存不足,因为当内存不足时kernel会释放缓存)
Total PSS by OOM adjustment:
169105 kB: Native
97363 kB: System
178249 kB: Persistent
60998 kB: com.android.systemui (pid 3322)
38981 kB: com.android.phone (pid 3352)
18122 kB: com.aliyun.ams.assistantservice (pid 4017)
15957 kB: com.meizu.cloud (pid 4074)
76388 kB: Foreground
41018 kB: com.meizu.flyme.launcher (pid 5537 / activities)
35370 kB: com.meizu.safe (pid 4373)
48876 kB: Visible
28633 kB: com.aliyun.ams.tyid (pid 5973)
12686 kB: com.meizu.cloud:mzservice_v1 (pid 4526)
7557 kB: com.amap.android.location (pid 3919)
39847 kB: Perceptible
27747 kB: com.meizu.flyme.input (pid 3903)
7478 kB: com.flyme.systemuitools (pid 5269)
4622 kB: system (pid 3935)
62405 kB: A Services
17735 kB: com.meizu.safe:Remote (pid 4776)
16603 kB: com.meizu.media.gallery:backup (pid 4300)
16502 kB: com.meizu.media.gallery (pid 4121)
11565 kB: android.process.media (pid 5759)
65237 kB: B Services
15641 kB: com.flyme.netadmin (pid 4887)
15624 kB: com.meizu.mzsyncservice (pid 4816)
12681 kB: com.meizu.flyme.service.find (pid 5379)
10678 kB: com.meizu.account (pid 5055)
272373 kB: Cached
61227 kB: com.android.mms (pid 5196)
42417 kB: com.android.settings (pid 5243)
33826 kB: android.process.acore (pid 5437)
28948 kB: com.meizu.mstore (pid 5850)
24945 kB: com.meizu.setup (pid 4160)
15667 kB: com.meizu.flyme.weather (pid 5878)
12113 kB: com.android.calendar:remote (pid 5522)
11282 kB: com.android.alarmclock (pid 5288)
9371 kB: com.meizu.flyme.update (pid 5406)
9088 kB: com.alipay.android.app (pid 5452)
7538 kB: com.android.providers.calendar (pid 4716)
5915 kB: com.mediatek.engineermode (pid 6105)
5132 kB: com.mediatek.schpwronoff (pid 5423)
4904 kB: com.mediatek.providers.drm (pid 5786)
Total PSS by OOM adjustment 中以
- Native
- System
- Persistent 常驻进程
- Foreground 前台进程
- Visible 可见进程,不在前台
- Perceptible
- A Services
- B Services
- Previous
- B Services
- Cached
对进程分组,OOM在内存低于某个阈值是会从Cached组内的进程开杀(内存占用越大的越先杀)。 所以当内存不足时释放Cached进程还不够用就会开始杀B Services组的进程。 为了保证更多的服务运行,系统(系统应用/服务)自身要减少内存占用,以供Service尽可能不被杀。 即使被杀了Android机制允许通过Bundle来存储应用当时的上下文,再启动时也可以无缝的还原当时现场,正所谓山寨版的Linux Swap内存机制。
当系统开始杀死LRU缓存里的进程时,尽管它主要从下往上工作,它同时也考虑了哪些进程消耗更多的内存,如果杀死它们,系统会得到更多的可用内存
2〉 dumpsys meminfo PID/Package
** MEMINFO in pid 8155 [com.meizu.media.gallery] **
Pss Private Private Swapped Heap Heap Heap
Total Dirty Clean Dirty Size Alloc Free
------ ------ ------ ------ ------ ------ ------
Native Heap 8561 7692 0 0 26816 23916 2899
Dalvik Heap 5273 4440 0 0 20281 18645 1636
Dalvik Other 951 944 0 0
Stack 652 652 0 0
Ashmem 25 0 0 0
Other dev 4 0 4 0
mmap (篇幅限制,此处不表)
Unknown 208 204 0 0
TOTAL 39817 15316 9768 0 47097 42561 4535
App Summary
Pss(KB)------
Java Heap: 5456
Native Heap: 7692
Code: 10048
Stack: 652
Graphics: 0
Private Other: 1236
System: 14733
TOTAL: 39817 TOTAL SWAP (KB): 0
Objects
Views: 0 ViewRootImpl: 0
AppContexts: 3 Activities: 0
Assets: 4 AssetManagers: 2
Local Binders: 33 Proxy Binders: 25
Parcel memory: 14 Parcel count: 56
Death Recipients: 1 OpenSSL Sockets: 0
Dalvik
isLargeHeap: true
SQL
MEMORY_USED: 562
PAGECACHE_OVERFLOW: 149 MALLOC_SIZE: 62
DATABASES
pgsz dbsz Lookaside(b) cache Dbname
4 20 29 1/18/2 /data/user/0/com.meizu.media.gallery/databases/folder.db
4 52 51 9/18/4 /data/user/0/com.meizu.media.gallery/databases/local_album_config.db
4 20 82 16/25/7 /data/user/0/com.meizu.media.gallery/databases/UsageStats.db
4 20 96 2/17/3 /data/user/0/com.meizu.media.gallery/databases/gallery_cloud_storage.db
4 36 95 43/84/14 /sdcard/Android/data/Gallery_local/galleryEx.db
- dumpsys meminfo PID/Package
- Heap Size: 代表最大总共分配空间
- Heap Alloc: 总共分配空间
- Heap Free: 代表总共剩余空间
- HeapSize是随着需求会往上涨, 直到触到最大值并报OOM异常
- Total PSS = Native PSS + Dalvik PSS + other PSS
3〉 procrank (注:该条命令仅eng的机器可以用)
root@a0255:/ # procrank
PID Vss Rss Pss Uss cmdline
1136 2887756K 222724K 104657K 92956K system_server
1349 3497108K 209428K 93992K 83928K com.android.systemui
1879 1174960K 126836K 46500K 38424K com.meizu.flyme.input
4622 1171896K 132404K 42263K 30216K com.meizu.net.search
3248 2126240K 151972K 42233K 34704K com.android.settings
2125 2576240K 152616K 40182K 32572K com.meizu.flyme.launcher
8155 1705252K 132656K 39604K 25072K com.meizu.media.gallery
2434 1717200K 146640K 39098K 30468K com.meizu.safe
查看每个进程内存占用情况
USS:针对单个应用内存泄露的关键指标
PSS:内存情况关注重点PSS段的使用量
4〉 showmap (注:该条命令仅eng的机器可以用)
root@a0255:/ # showmap -t 8155(com.meizu.media.gallery)
virtual shared shared private private
size RSS PSS clean dirty clean dirty # object
-------- -------- -------- -------- -------- -------- -------- ---- ------------------------------
12492 12380 1655 664 1700 0 1016 2 /data/dalvik-cache/arm/system@framework@boot.art
20808 15708 11614 8188 0 7516 4 3 /data/dalvik-cache/arm/system@priv-app@Gallery@Gallery.apk@classes.dex
896 716 621 0 100 0 616 7 /dev/ashmem/dalvik-LinearAlloc (deleted)
8192 48 48 0 0 0 48 1 /dev/ashmem/dalvik-allocspace main rosalloc space 1 live-bitmap 2 (deleted)
1004 4 4 0 0 0 4 1 /dev/ashmem/dalvik-allocspace non moving space live-bitmap 4 (deleted)
13144 40 40 0 0 0 40 1 /dev/ashmem/dalvik-card table (deleted)
1976 184 184 0 0 0 184 49 /dev/ashmem/dalvik-indirect ref table (deleted)
128 20 20 0 0 0 20 1 /dev/ashmem/dalvik-large marked objects (deleted)
15784 15704 2189 0 14172 0 1532 320 /dev/ashmem/dalvik-large object space allocation (deleted)
8196 8 8 0 0 0 8 1 /dev/ashmem/dalvik-live stack (deleted)
524288 2500 2500 0 0 0 2500 1 /dev/ashmem/dalvik-main space 1 (deleted)
4 4 4 0 0 0 4 1 /dev/ashmem/dalvik-mod union bitmap (deleted)
64096 56 56 0 0 0 56 4 /dev/ashmem/dalvik-non moving space (deleted)
256 4 4 0 0 0 4 2 /dev/ashmem/dalvik-rosalloc page map (deleted)
1440 1440 261 0 1248 0 192 1 /dev/ashmem/dalvik-zygote space (deleted)
128 112 10 100 4 0 8 3 /system/bin/linker
............................................. .so
9900 4636 3083 2716 0 1716 204 8 /system/priv-app/Gallery/Gallery.apk
27136 21684 8475 0 13980 0 7704 44 [anon:libc_malloc]
108 108 60 0 48 0 60 22 [anon:linker_alloc]
4 4 4 0 0 0 4 1 [anon:linker_alloc_128]
4 4 4 0 0 0 4 1 [anon:linker_alloc_16]
4 4 4 0 0 0 4 1 [anon:linker_alloc_32]
4 4 4 0 0 0 4 1 [anon:linker_alloc_64]
20 20 16 0 4 0 16 5 [anon:linker_alloc_vector]
544 4 4 0 0 0 4 68 [anon:thread signal stack]
103208 60 40 0 20 0 40 191 [anon]
-------- -------- -------- -------- -------- -------- -------- ---- ------------------------------
virtual shared shared private private
size RSS PSS clean dirty clean dirty # object
-------- -------- -------- -------- -------- -------- -------- ---- ------------------------------
1708392 132464 38941 72664 34860 9768 15172 1568 TOTAL
22084 2848 748 2116 716 0 16 4 /system/lib/egl/libGLES_mali.so
56 44 22 32 0 0 12 3 /system/lib/hw/gralloc.mt6755.so
428 112 24 56 40 0 16 5 /system/lib/libEGL.so
916 368 38 304 60 0 4 5 /system/lib/libandroid_runtime.so
172 108 11 100 4 0 4 4 /system/lib/libandroidfw.so
3376 1680 119 1632 36 0 12 4 /system/lib/libaoc.so
184 108 8 76 28 0 4 4 /system/lib/libbinder.so
572 128 16 104 16 0 8 5 /system/lib/libc++.so
532 392 42 336 28 0 28 4 /system/lib/libc.so
664 416 42 368 44 0 4 4 /system/lib/libcrypto.so
72 60 5 52 4 0 4 4 /system/lib/libcutils.so
276 112 64 96 0 0 16 4 /system/lib/libdlna_jni.so
28 20 5 12 4 0 4 4 /system/lib/libgralloc_extra.so
412 152 25 96 52 0 4 4 /system/lib/libgui.so
452 332 96 312 16 0 4 3 /system/lib/libhwui.so
1472 384 52 328 44 8 4 3 /system/lib/libicui18n.so
1144 568 69 512 48 0 8 4 /system/lib/libicuuc.so
216 140 13 128 8 0 4 4 /system/lib/libjavacore.so
836 212 25 76 132 0 4 3 /system/lib/libmedia.so
300 72 15 52 16 0 4 5 /system/lib/libmedia_jni.so
68 52 12 44 4 0 4 3 /system/lib/libminikin.so
28 20 4 12 4 0 4 3 /system/lib/libmtk_drvb.so
36 32 6 24 4 0 4 3 /system/lib/libmtksqlite3_android.so
36 28 5 20 4 0 4 3 /system/lib/libnativehelper.so
32 24 6 16 4 0 4 3 /system/lib/libperfservicenative.so
68 56 6 48 4 0 4 4 /system/lib/libselinux.so
3932 672 166 508 104 48 12 4 /system/lib/libskia.so
408 360 45 344 8 0 8 4 /system/lib/libsqlite.so
184 136 15 124 8 0 4 3 /system/lib/libssl.so
96 64 12 52 8 0 4 4 /system/lib/libui.so
104 76 8 68 4 0 4 3 /system/lib/libutils.so
5〉 adb shell top
C:\Users\zephy>adb shell top -m 5 -d 10
User 6%, System 5%, IOW 0%, IRQ 0%
User 65 + Nice 1 + Sys 55 + Idle 949 + IOW 1 + IRQ 0 + SIRQ 0 = 1071
PID PR CPU% S #THR VSS RSS PCY UID Name
1136 0 4% S 142 2888184K 221408K fg system system_server
1349 0 1% S 51 3497112K 258628K fg u0_a31 com.android.systemui
9708 1 1% R 1 14156K 1596K fg root top
341 3 1% S 32 1766776K 50288K fg system /system/bin/surfaceflinger
2634 0 0% S 24 1692960K 118940K bg system com.meizu.safe:Remote
User 6%, System 5%, IOW 0%, IRQ 0% CPU占用率
User 65 + Nice 1 + Sys 55 + Idle 949 + IOW 1 + IRQ 0 + SIRQ 0 = 1071 CPU使用情况/所占进程数
Usage: top [-m max_procs] [-n iterations] [-d delay] [-s sort_column] [-t] [-h]
-m num Maximum number of processes to display. // 最多显示多少个进程
-n num Updates to show before exiting. // 刷新次数
-d num Seconds to wait between updates. // 刷新间隔时间(默认5秒)
-s col Column to sort by <cpu,vss,rss,thr> // 按哪列排序
-t Show threads instead of processes. // 显示线程信息而不是进程
-h Display this help screen. // 显示帮助文档
6〉 adb shell ps
127|shell@a0255:/ $ ps 6720
USER PID PPID VSIZE RSS WCHAN PC NAME
u0_a74 6720 499 1108240 93480 SyS_epoll_ 0000000000 S com.meizu.media.reader
Usage: ps [-m max_procs] [-n iterations] [-d delay] [-s sort_column] [-t] [pid] [name]
-t 显示进程下的线程列表
-x 显示进程耗费的用户时间和系统时间,格式:(u:0, s:0),单位:秒(s) [pid] 过滤指定的进程PID [name] 过滤指定的进程NAME
PS 仅提供当前进程内存/CPU使用快照 Top 可实时提供进程信息,即时查看最活跃的进程,但top比较消耗系统资源
3、测试项目
- 实现ONTRIMMEMORY()(释放缓存)
- ACTIVITY & VIEW、VIEWROOTIMPL 的泄露排查
- 总内存
- 内存抖动
1)OnTrimMemory
About OnTrimMemory( ) 作用:指导应用程序在不同的情况下进行自身的内存释放,以避免被系统直接杀掉,提高应用程序的用户体验. 提示开发者在系统内存不足的时候,通过处理部分资源来释放内存。
OnTrimMemory回调中可以释放哪些资源? 缓存 缓存包括一些文件缓存,图片缓存等,在用户正常使用的时候这些缓存很有作用,但当你的应用程序UI不可见的时候,这些缓存就可以被清除以减少内存的使用.比如第三方图片库的缓存. 一些动态生成动态添加的View. 这些动态生成和添加的View且少数情况下才使用到的View,这时候可以被释放,下次使用的时候再进行动态生成即可.
2〉activity、view泄露检查
操作前提:根据用例随机操作,back到桌面 【activity生命流程 执行 onDestory()】
方法: 1. Apt 工具
2. adb shell dumpsys meminfo -> objects
3. Memory Analyzer tool(MAT) 分析离线数据
4. profiling/monitoring(AS)
① 桌面、SystemUI、信息、联系人、电话: Views/Activites/ViewRootImpls数目允许大于0,但是所这些应用而言,不论怎样随机反复操作,三项数目不能一直增大
② 其他应用三值销毁为0
** MEMINFO in pid 8155 [com.meizu.media.gallery] **
Objects
Views: 0 ViewRootImpl: 0
AppContexts: 3 Activities: 0
Assets: 4 AssetManagers: 2
Local Binders: 33 Proxy Binders: 25
Parcel memory: 14 Parcel count: 56
Death Recipients: 1 OpenSSL Sockets: 0
3〉总内存( PSS Total )
1、SystemUI在没有更换主题前提下,点击多任务的一键清理后PSS Total不能大于120M(1080P)机型
2、其他应该使用过程中PSS Total不能大于256M(1080P屏幕)
4〉 内存抖动
多指列表滑动,同尺寸图片切换场景下,内存抖动异常的测试 如通话列表(3000条)滑动时,总内存(PSStotal)不能波动频繁
5)SUMMARY
** MEMINFO in pid 8155 [com.meizu.media.gallery] **
Pss Private Private Swapped Heap Heap Heap
Total Dirty Clean Dirty Size Alloc Free
------ ------ ------ ------ ------ ------ ------
Native Heap 8561 7692 0 0 26816 23916 2899
Dalvik Heap 5273 4440 0 0 20281 18645 1636
Dalvik Other 951 944 0 0
Stack 652 652 0 0
Ashmem 25 0 0 0
Other dev 4 0 4 0
mmap (篇幅限制,此处不表)
Unknown 208 204 0 0
TOTAL 39817 15316 9768 0 47097 42561 4535
App Summary
Pss(KB)------
Java Heap: 5456
Native Heap: 7692
Code: 10048
Stack: 652
Graphics: 0
Private Other: 1236
System: 14733
TOTAL: 39817 TOTAL SWAP (KB): 0
Objects
Views: 0 ViewRootImpl: 0
AppContexts: 3 Activities: 0
Assets: 4 AssetManagers: 2
Local Binders: 33 Proxy Binders: 25
Parcel memory: 14 Parcel count: 56
Death Recipients: 1 OpenSSL Sockets: 0
Dalvik
isLargeHeap: true
SQL
MEMORY_USED: 562
PAGECACHE_OVERFLOW: 149 MALLOC_SIZE: 62
DATABASES
pgsz dbsz Lookaside(b) cache Dbname
4 20 29 1/18/2 /data/user/0/com.meizu.media.gallery/databases/folder.db
4 52 51 9/18/4 /data/user/0/com.meizu.media.gallery/databases/local_album_config.db
4 20 82 16/25/7 /data/user/0/com.meizu.media.gallery/databases/UsageStats.db
4 20 96 2/17/3 /data/user/0/com.meizu.media.gallery/databases/gallery_cloud_storage.db
4 36 95 43/84/14 /sdcard/Android/data/Gallery_local/galleryEx.db
4、内存测试自动化相关工具
测试项 | 条件 |
电话 | 2000条 |
通话记录 | 100条 |
联系人 | 3000条 |
短信 | 3000条 |
便签 | 100个 |
桌面图标 | 9页铺满,且包含文件夹, 文件夹有15个图标 |
通知栏信息 | 50条 |
图片 | 图库文件夹50个 图片缩略图500张照片10个文件夹 |
视频 | 200个(含10个文件夹)在线缓存20个 |
音乐 | 1000首(带封面) |
邮件1000封 | 1000~3000(至少含有一封50次会话的邮件)
|
下载管理 | 50个任务下载 |
网页浏览 | 7个网页 |
天气 | 34种 |
文档 | 100 |