问题
最近在项目中遇到一个 Low on memory
内存过高导致应用退出问题,其中使用了一些内存查看命令,这里做一个记录,错误日志如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| I/ActivityManagerService( 443): Low on memory:
I/ActivityManagerService( 443): ntv N 4118 kB: zygote (pid 161) native
I/ActivityManagerService( 443): ntv N 2814 kB: surfaceflinger (pid 142) native
I/ActivityManagerService( 443): ntv N 1986 kB: logd (pid 136) native
I/ActivityManagerService( 443): ntv N 1925 kB: mediaserver (pid 157) native
I/ActivityManagerService( 443): ntv N 2749 kB: (Other native)
I/ActivityManagerService( 443): sys P 24827 kB: system (pid 443) fixed
I/ActivityManagerService( 443): pers P 37707 kB: com.android.systemui (pid 612) fixed
I/ActivityManagerService( 443): pers P 13423 kB: com.android.phone (pid 819) fixed
I/ActivityManagerService( 443): pers P 8760 kB: com.android.inputmethod.latin (pid 706) fixed
I/ActivityManagerService( 443): pers P 5996 kB: android.process.media (pid 575) fixed
I/ActivityManagerService( 443): pers P 3577 kB: com.cghs.stresstest (pid 796) fixed
I/ActivityManagerService( 443): fore T 153394 kB: com.dlc.huishouxiang (pid 24324) top-activity
I/ActivityManagerService( 443): 261276 kB: TOTAL
I/ActivityManagerService( 443): MemInfo: 25032 kB slab, 140 kB shmem, 379704 kB vm alloc, 7532 kB page el stack
I/ActivityManagerService( 443): 132 kB buffers, 86556 kB cached, 42500 kB mapped, 180476 kB free
I/ActivityManagerService( 443): ZRAM: 5652 kB RAM, 520908 kB swap total, 503928 kB swap free
I/ActivityManagerService( 443): Free RAM: 224664 kB
I/ActivityManagerService( 443): Used RAM: 677980 kB
I/ActivityManagerService( 443): Lost RAM: 1158732 kB
I/ActivityManagerService( 443): Start proc 3350:com.android.smspush/u0a43 for service com.android.smspush/.WapPushManager
|
从日志上 18 ~ 20 行看 Lost RAM
占用太大了,而 Used RAM
占用并不大。
Free RAM:为剩余内存。
Used RAM:为用户态使用总内存。
Lost RAM:为内核态使用内存,比如 OpenGL 纹理内存、GPU 占用内存、图形显示 ION buffer 都包含在 Lost RAM 里,从字面意思是理解它是丢失的内存,也就是说它是操作系统无法解释和正常利用的内存。
其中 Lost RAM
= TotalRAM
- FreeRAM
- UsedRAM
也可以理解为其他内存。
查看内存分配
为了进一步分析,我们接下来使用 adb 命令观察应用内存分配情况。
1
| adb shell dumpsys meminfo <package_name|pid> [-d]
|
-d
标志会打印与 Dalvik 和 ART 内存使用情况相关的更多信息。 pid
可以通过 adb shell ps
查看。
此命令会列出应用的所有当前内存分配,单位为 KB。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| shell@rk3288_box:/ $ dumpsys meminfo 1418
Applications Memory Usage (kB):
Uptime: 2171528 Realtime: 2171528
** MEMINFO in pid 1418 [com.dlc.huishouxiang] **
Pss Private Private Swapped Heap Heap Heap
Total Dirty Clean Dirty Size Alloc Free
------ ------ ------ ------ ------ ------ ------
Native Heap 9647 9556 0 0 12868 11028 1839
Dalvik Heap 54158 54040 0 0 56026 52280 3746
Dalvik Other 1096 1096 0 0
Stack 484 484 0 0
Other dev 5 0 4 0
.so mmap 4749 436 2048 0
.apk mmap 344 0 80 0
.ttf mmap 33 0 20 0
.dex mmap 10780 0 10776 0
.oat mmap 3740 0 1404 0
.art mmap 1820 1168 144 0
Other mmap 1096 4 520 0
Unknown 166 164 0 0
TOTAL 88118 66948 14996 0 68894 63308 5585
Objects
Views: 900 ViewRootImpl: 3
AppContexts: 5 Activities: 2
Assets: 2 AssetManagers: 2
Local Binders: 53 Proxy Binders: 26
Parcel memory: 11 Parcel count: 44
Death Recipients: 0 OpenSSL Sockets: 0
SQL
MEMORY_USED: 134
PAGECACHE_OVERFLOW: 37 MALLOC_SIZE: 62
DATABASES
pgsz dbsz Lookaside(b) cache Dbname
4 52 109 73/42/16 /data/data/com.dlc.huishouxiang/databases/bugly_db_
|
Private Clean
和 Private Dirty
是仅供给应用进程使用的内存,这里的内存当应用程序被销毁时大部分会被释放掉。一般来说这一部分内存很重要,这些内存只存在于 RAM 中。
Pss
是对应用程序内存使用情况的一个衡量,包含了进程间的共享账户和共享页面。进程所独有的资源加上按比例分成的共享资源,例如两个进程之间共享页面将为每个进程的 Pss 贡献一半大小。它是衡量进程内存使用情况的一个很重要指标,它最接近于进程的实际使用内存。
Dalvik Heap
Dalvik 给你应用程序分配的 RAM 大小,Pss Total
包括所有 Zygote 分配(上面提到过 PSS 通过进程之间共享的内存容量来衡量),Private Dirty
指的是分配给应用程序本身的实际 RAM 大小(不包含共享部分)。
详细内存信息
使用 cat /proc/meminfo
可以查看更加详细的内存信息。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
| root@phone:/ # cat /proc/meminfo
MemTotal: 2857.032 kB //RAM可用的总大小 (即物理总内存减去系统预留和内核二进制代码大小)
MemFree: 1020.708 kB //RAM未使用的大小
Buffers: 75.104 kB //用于文件缓冲
Cached: 448.244 kB //用于高速缓存
SwapCached: 0 kB //用于swap缓存
Active: 832.900 kB //活跃使用状态,记录最近使用过的内存,通常不回收用于其它目的
Inactive: 391.128 kB //非活跃使用状态,记录最近并没有使用过的内存,能够被回收用于其他目的
Active(anon): 700.744 kB //Active = Active(anon) + Active(file)
Inactive(anon): 228 kB //Inactive = Inactive(anon) + Inactive(file)
Active(file): 132.156 kB
Inactive(file): 390.900 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 524.284 kB //swap总大小
SwapFree: 524.284 kB //swap可用大小
Dirty: 0 kB //等待往磁盘回写的大小
Writeback: 0 kB //正在往磁盘回写的大小
AnonPages: 700.700 kB //匿名页,用户空间的页表,没有对应的文件
Mapped: 187.096 kB //文件通过mmap分配的内存,用于map设备、文件或者库
Shmem: .312 kB
Slab: 91.276 kB //kernel数据结构的缓存大小,Slab=SReclaimable+SUnreclaim
SReclaimable: 32.484 kB //可回收的slab的大小
SUnreclaim: 58.792 kB //不可回收slab的大小
KernelStack: 25.024 kB
PageTables: 23.752 kB //以最低的页表级
NFS_Unstable: 0 kB //不稳定页表的大小
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 1952.800 kB
Committed_AS: 82204.348 kB //评估完成的工作量,代表最糟糕case下的值,该值也包含swap内存
VmallocTotal: 251658.176 kB //总分配的虚拟地址空间
VmallocUsed: 166.648 kB //已使用的虚拟地址空间
VmallocChunk: 251398.700 kB //虚拟地址空间可用的最大连续内存块
|
参考文档:
https://developer.android.com/studio/command-line/dumpsys#meminfo
http://gityuan.com/2016/01/02/memory-analysis-command/