linux iwap虚拟内存,性能优化工具(十)- Android内存分析命令

一、内存指标

Item

全称

含义

等价

USS

Unique Set Size

物理内存

进程独占的内存

PSS

Proportional Set Size

物理内存

PSS= USS+ 按比例包含共享库

RSS

Resident Set Size

物理内存

RSS= USS+ 包含共享库

VSS

Virtual Set Size

虚拟内存

VSS= RSS+ 未分配实际物理内存

内存的大小关系:VSS >= RSS >= PSS >= USS

二、常用内存分析命令

1 procrank

获取所有进程的内存使用的排行榜,排行是以Pss的大小而排序,能输出详细的VSS/RSS/PSS/USS内存指标。

PID Vss Rss Pss Uss Swap PSwap USwap ZSwap cmdline

1479 2748552K 382328K 224152K 168908K 26040K 16185K 15944K 3575K system_server

...

1817679K 1618480K 1530116K 470311K 433840K 103909K TOTAL

ZRAM: 111212K physical used for 503364K in swap (1048572K total swap)

RAM: 2914764K total, 41284K free, 11904K buffers, 592500K cached, 11672K shmem, 183752K slab

2 free

查看可用内存,缺省单位KB。该命令比较简单、轻量,专注于查看剩余内存情况。数据来源于/proc/meminfo。

total used free shared buffers

Mem: 2984718336 2946801664 37916672 11943936 11337728

-/+ buffers/cache: 2935463936 49254400

Swap: 1073737728 515416064 558321664

对于Mem行,存在的公式关系: total = used + free;

对于-/+ buffers行:buffers/cache used = mem used - mem buffers

buffers/cache free = mem free + mem buffers

3 cat /proc/meminfo

展示的是系统整体内存情况,内存项按类型进行分类:

MemTotal: 2914764 kB 内存总数 (除去BIOS和内核预留的内存,剩下可供系统支配的内存)

MemFree: 78008 kB 系统空闲内存(系统尚未被使用的,total-free = used)

MemAvailable: 440972 kB 可用内存(memfree + 可回收内存(部分buffer/cached,slab也能回收一部分))

Buffers: 14200 kB 缓冲区内存(给文件做缓冲的)

Cached: 566648 kB 缓存区内存(被高速缓冲存储器(cache memory)用的内存)

SwapCached: 60560 kB 缓存区中已经被交换出来的内存

Active: 1243832 kB 在活跃使用中的缓冲或高速缓冲存储器页面文件的大小,除非非常必要否则不会被移作他用

Inactive: 576108 kB 在不经常使用中的缓冲或高速缓冲存储器页面文件的大小,可能被用于其他途径

Active(anon): 1043860 kB

Inactive(anon): 377368 kB

Active(file): 199972 kB

Inactive(file): 198740 kB

Unevictable: 173940 kB

Mlocked: 173940 kB 被系统锁定的页面

SwapTotal: 1048572 kB 交换空间的总大小(设置的zram交换空间大小)

SwapFree: 471124 kB 未被使用交换空间的大小

Dirty: 72 kB 等待被写回到磁盘的内存大小

Writeback: 0 kB 正在被写回到磁盘的内存大小

AnonPages: 1407356 kB 未映射页的内存大小

Mapped: 435656 kB 已经被设备和文件等映射的内存大小

Shmem: 8388 kB 共享内存大小

Slab: 176044 kB 内核中slab分配的内存大小(slab = SReclaimable+SUnreclaim)

SReclaimable: 55528 kB 可收回Slab的内存大小

SUnreclaim: 120516 kB 不可收回Slab的内存大小

KernelStack: 56144 kB 内核栈区大小

PageTables: 61256 kB 内存管理的分页的页表大小

NFS_Unstable: 0 kB 不稳定页表的大小

Bounce: 0 kB

WritebackTmp: 0 kB

CommitLimit: 2505952 kB

Committed_AS: 95946620 kB

VmallocTotal: 258998208 kB 可以被vmalloc分配的虚拟内存大小

VmallocUsed: 142860 kB 已经被使用的虚拟内存大小

VmallocChunk: 258740196 kB

日常使用经验总结:

1)MemTotal: 是除去系统底层预留内存之外,能被系统使用的总内存大小,正常情况下会比实际内存小一点,但是如果小太多的话属于预留不合理,需要看看原因,这属于先天不足,天花板过低。

2)MemFree 、MemAvailable: 前者是当前系统未被使用的内存,后者是当前系统可以被使用的内存(包括可以被回收的部分内存),意思就那个什么,挤挤还是有的。从经验上来说,如果当前MemAvailable底于总内存的1/10,那么系统可能会出现因为内存造成的卡顿,其中原因可能包括频繁回收内存造成的阻塞、耗时以及寻址难度加大变相地增加了内存分配的时间等等。

3)Buffers 、Cached: 前者用于缓存磁盘blocks以优化block I/O,后者用于缓存文件内容以优化文件I/O。部分内存是可被回收的,被算到MemAvailable中。MemAvailable ≈ MemFree+Buffers+Cached。

4)Mlocked: 被系统锁定的页面。比如系统中google 7.0加的PinnerService 就会有这个效果,把常用的内容锁定在内存中,避免频繁的内存回收与分配,优化但不限于提升io效率。典型的用空间换时间,如果是Android 2G及其以下内存的手机,建议关闭PinnerService,要啥自行车。PinnerService官方描述

5)SwapTotal、SwapFree: 这就zram,如果为0就是没打开。SwapTotal是zram总空间大小,SwapFree是没交换的空间大小。

6)Slab: 内核基于Buddy做了page的粗分,Slab基于Buddy做了内存二次划分,这部分就是基于Slab内存分配的内存大小。使用的函数是kmalloc/kfree。 SReclaimable和SUnreclaim分别是Slab的可回收和不可回收部分(slab = SReclaimable+SUnreclaim),如果Slab比较大,可能是kernel debug开关被打开了(也不一定,具体看调试内容),而且SUnreclaim也非常大的话,可能存在kernel泄漏。

7)Kernel内存可使用内存 ≈ Slab + KernelStack + PageTables。

4 dumpsys meminfo

4.1 dumpsys实现逻辑简单介绍

dumpsys的源码结构其实很简单,只有一个dumpsys.cpp

源码路径是:/frameworks/native/cmds/dumpsys/dumpsys.cpp

在其main方法中,先通过defaultServiceManager()函数获得ServiceManager对象,然后根据dumpsys传进来的参数通过函数checkService来找到具体的service, 并执行该service的dump方法,达到dump service的目的。

4.2 dumpsys meminfo 数据组成

dumpsys meminfo对应的服务是:ActivityManagerService, 它从memBinder类的dump函数开始执行的。

static class MemBinder extends Binder {

ActivityManagerService mActivityManagerService;

MemBinder(ActivityManagerService activityManagerService) {

mActivityManagerService = activityManagerService;

}

@Override

protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {

if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)

!= PackageManager.PERMISSION_GRANTED) {

pw.println("Permission Denial: can't dump meminfo from from pid="

+ Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()

+ " without permission " + android.Manifest.permission.DUMP);

return;

}

mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args, false, null);

}

}

主要收集内存信息并打印是在dumpApplicationMemoryUsage方法中做的,但是该方法比较大,就不列出来了,举个例子:

Debug.getMemoryInfo(pid, mi);//通过debug.java中的getMemoryInfo函数来获取当前进程的整体memory信息,获取的是对应的/proc/$/smaps文件统计出来的信息。getMemoryInfo是个native方法,对应到android_os_Debug.cpp的android_os_Debug_getDirtyPagesPid。

从代码看:这部分内容是从/proc/$/smaps获取的。

那么总结下dumpsys meminfo的出处:

9edfe9d5eb34?utm_source=desktop&utm_medium=timeline

很明显,dumpsys meminfo 获取的数据是从系统各个渠道汇集来的。

4.3 dumpsys meminfo 展示的是系统整体内存情况, 内存项按进程进行分类

Total PSS by process: Java层存活的进程及其占用内存情况

241,086K: system (pid 1479)

161,423K: surfaceflinger (pid 544)

137,754K: com.android.systemui (pid 4843 / activities)

...

Total PSS by OOM adjustment: Native存活的进程及其占用内存情况

376,783K: Native

161,423K: surfaceflinger (pid 544)

14,303K: audioserver (pid 725)

9,247K: zygote (pid 719)

...

576,007K: Persistent 按进程优先级分别来统计对应的进程及其内存使用情况, 列举几个:

241,086K: system (pid 1479)

...

219,381K: Foreground

167,657K: com.tengxin.youqianji (pid 29421 / activities)

...

317,970K: B Services

33,115K: com.UCMobile:channel (pid 25225)

...

410,541K: Cached

36,294K: com.android.vending (pid 13418)

...

Total PSS by category: 按类型进行分类

555,972K: Dalvik

401,562K: Native

154,436K: EGL mtrack

151,504K: Unknown

145,638K: .oat mmap

118,919K: .dex mmap

118,259K: .art mmap

88,952K: GL mtrack

73,583K: Dalvik Other

51,418K: Gfx dev

39,993K: .so mmap

28,950K: .apk mmap

27,075K: Stack

9,919K: Ashmem

6,219K: Other mmap

1,968K: Other dev

120K: .jar mmap

80K: .ttf mmap

16K: Cursor

0K: Other mtrack

Total RAM: 2,914,764K (status normal)

Free RAM: 1,208,341K ( 410,541K cached pss + 730,784K cached kernel + 2,676K cached ion + 64,340K free)

Used RAM: 2,326,986K (1,994,786K used pss + 332,200K kernel)

Lost RAM: -16,504K

ZRAM: 101,812K physical used for 466,040K in swap (1,048,572K total swap)

Tuning: 192 (large 512), oom 322,560K, restore limit 107,520K (high-end-gfx)

先总结下最下面的统计:

Total RAM:内存总数,与proc/meminfo中的MemTotal一致。

Free RAM:cached pss + cached kernel + cached ion + free 手机剩余内存一般是看它

cached pss:dumpsys meminfo中 cached 进程的PSS总和

cached kernel:这个暂时无定论

free:proc/meminfo 的MemFree

ion cached以及gpu cached:display相关ion的内存占用

Used RAM:used pss+kernel+trace buffer+ion display+cma usage

used pss:native process PSS+dumpsys meminfo APP除cached部分的PSS总和

kernel:meminfo的Shmem+Slab+PageTables+kernelStack+vmallocinfo里面的ioremap项+map_lowmem项所占内存的和

ion disp:display相关的ion模块内存占用

cma usage:cma模块占用

Lost RAM:与cache ion有关

ZRAM:zram swap转换情况

Tuning:这一行主要是system的一些设置,没看过

5 dumpsys meminfo [pid | packageName]

查看单个进程内存详情

** MEMINFO in pid 1479 [system] **

Pss Private Private SwapPss Heap Heap Heap

Total Dirty Clean Dirty Size Alloc Free

------ ------ ------ ------ ------ ------ ------

Native Heap 26106 25984 104 8739 73728 34267 39460

Dalvik Heap 63706 63676 4 1858 56528 40144 16384

Dalvik Other 6704 6668 12 24

Stack 2388 2364 24 1352

Ashmem 8004 8000 0 0

Gfx dev 532 124 0 0

Other dev 55 8 36 0

.so mmap 1561 444 780 488

.jar mmap 0 0 0 8

.apk mmap 145 0 0 0

.dex mmap 28702 0 4428 40

.oat mmap 78494 0 49992 0

.art mmap 3068 2684 76 856

Other mmap 34 4 0 0

GL mtrack 1424 1424 0 0

Unknown 1275 1084 188 2882

TOTAL 238445 112464 55644 16247 130256 74411 55844

App Summary

Pss(KB)

------

Java Heap: 66436

Native Heap: 25984

Code: 55644

Stack: 2364

Graphics: 1548

Private Other: 16132

System: 70337

TOTAL: 238445 TOTAL SWAP PSS: 16247

Objects

Views: 3 ViewRootImpl: 1

AppContexts: 20 Activities: 0

Assets: 8 AssetManagers: 6

Local Binders: 888 Proxy Binders: 1652

Parcel memory: 1697 Parcel count: 751

Death Recipients: 753 OpenSSL Sockets: 0

数据来源:

9edfe9d5eb34?utm_source=desktop&utm_medium=timeline

纵轴:

属性名

说明

Native Heap

在 Native Code 中使用 malloc 分配出的内存

Dalvik Heap

Dalvik 虚拟机分配的空间,不包括它自身的开销。Dalvik 堆中和 Zygote 进程共享的部分算是 sharedDirty

Dalvik Other

类数据结构和索引占据的内存

Stack

栈内存

Cursor

CursorWindow 占用的空间,与 SQL 有关

Ashmem

匿名共享内存,此类内存与 cache shrinker 关联,可以控制cache shrinker在适当时机回收这些共享内存

Gfx dev

/dev/kgsl-3d0 占用的内存

Other dev

内部driver占用的内存

.so mmap

映射的 .so(native)代码占用的内存

.jar mmap

Java 文件代码占用内存

.apk mmap

apk 代码占用内存

.ttf mmap

ttf 文件代码占用内存

.dex mmap

映射的 .dex(Dalvik 或 ART)代码占用的内存

.oat mmap

代码映像占用的 RAM 量。此映像在所有应用之间共享,不受特定应用影响

.art mmap

堆映像占用的 RAM 量。此映像在所有应用之间共享,不受特定应用影响。尽管 ART 映像包含 Object 实例,它仍然不会计入您的堆大小

Other mmap

其它文件占用的内存

横轴:

属性名

说明

Pss Total

实际使用的内存,这里考虑了与 Zygote 的共享。任何独占的内存页直接计算它的PSS值,而和其它进程共享的页则按照共享的比例计算PSS值

Private Dirty

进程私有的,相对磁盘数据有改动的内存

Private Clean

进程私有的,相对磁盘数据没有修改的内存

SwapPss Dirty

Android 4.4 的一个优化,swap to zRAM。牺牲CPU,减少内存。这两个值的区别在于内核是否是统计按比例分出的swap数据,是的输出为 SwapPss Dirty。

Swap Dirty

Whether the kernel reports proportional swap usage

Heap相关:

Heap Size

Heap Alloc

Heap Free

Native Heap

从mallinfo usmblks获得,代表最大总共分配空间

从mallinfo uorblks获得,总共已分配空间

从mallinfo fordblks获得,代表总共剩余空间

Dalvik Heap

从Runtime totalMemory()获得,Dalvik Heap总共的内存大小

Runtime totalMemory()-freeMemory() ,Dalvik Heap分配的内存大小

从Runtime freeMemory()获得,Dalvik Heap剩余的内存大小

App Summary:

9edfe9d5eb34?utm_source=desktop&utm_medium=timeline

属性名

内存组成

Java Heap

Dalvik Heap 的 Private Dirty

.art mmap 的 Private Dirty + Private Clean

Native Heap

Native Heap 的 Private Dirty

Code

.so mmap

.jar mmap

.apk mmap

.ttf mmap

.dex mmap

.oat mmap的 Private Dirty + Private Clean

Stack

Stack 的 Private Dirty

Graphics

Gfx dev

EGL mtrack

GL mtrack的 Private Dirty + Private Clean

Private Other

Native Heap

Dalvik Heap

- HEAP_UNKNOWN的 Private Dirty + Private Clean

System

Native Heap

Dalvik Heap

HEAP_UNKNOWN的 Pss + SwapPss Dirty - Private Dirty - Private Clean

TOTAL

Native Heap

Dalvik Heap

HEAP_UNKNOWN的 Pss + SwapPss Dirty

TOTAL SWAP PSS

Native Heap

Dalvik Heap

HEAP_UNKNOWN的 SwapPss Dirty

TOTAL SWAP (KB)

Native HEAP

Dalvik Heap

HEAP_UNKNOWN的 Swap Dirty

Object:

9edfe9d5eb34?utm_source=desktop&utm_medium=timeline

这里通常会通过看Activities、AppContexts来判断是否有内存泄漏,比如刚退出应用,查看Object中Activities是否为0,如果不为0,则有Activity没有销毁,很有可能存在泄漏。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值