android 内存消耗分析
1、如何查看memory 的总消耗
linux的命令top -h 以及PS 都可以查看到内存PSS和VSS的内存消耗。android提供了工具,可以更全面的分析到内存的分布情况。先看procrank,这个工具没有,可以通过下载编译放在android /system/xbin/目录下。然后分别执行:
adb root
adb shell procrank
我们看一下内存分布结果:
PID Vss Rss Pss Uss Swap PSwap USwap ZSwap cmdline 1012 1552016K 214564K 131199K 120700K 25304K 20554K 20356K 10391K xxx.xxxx.xxx(进程名)
我们发现一个关系,VSS>RSS>PSS>USS(实际都是>=),那他们有什么区别呢?为什么存在大小差别。
首先是VSS,Virtual Set Size,也就是虚拟耗用内存,它包含了所有的分配的内存,这部分内存有可能还未使用。所以称为虚拟。除了包含本进程的分配内存,它还包含了共享库的内存。
RSS,Resident Set Size ,实际使用物理内存,因此他只包含了使用的内存,他除了包含自己使用的内存,还包含了所有的共享库的内存。
PSS,Proportional Set Size,实际使用物理内存,上面RSS讲到,会将所有的共享库的内存都算进来,如果很多程序都在使用共享库的内存,会造成全算到一个进程RSS里面,显然是不准确的,PSS则将共享库内存进行平均,算到每一个使用其的PSS内存里。
Uss,Unique Set Size ,进程独自占用内存,顾名思义,就是剥离了共享库的内存值。这个能更精确的反应当前进程本身的内存使用状况。
注:共享的内存怎么理解,比如调用很多公有服务,使用公有的库,这部分库的内存实际只会载入一次,所以这部分的内存归属问题,才有了现在这么多分组。
2、如何查看应用具体内存情况
这个就是我们常用的adb shell dumpsys meminfo xxxx(进程名)。
为什么我们这边一定强调一定是进程名,因为linux的内存页分配都是以进程为单位的,虽然默认情况下单进程的app,进程名就是app的包名。但是必须要强调。
我们看一个结果:
Applications Memory Usage (in Kilobytes):Uptime: 3168126 Realtime: 3168126** MEMINFO in pid 1012 [XXX.XXX.XXX(进程名)] ** Pss Private Private SwapPss Heap Heap Heap Total Dirty Clean Dirty Size Alloc Free ------ ------ ------ ------ ------ ------ ------ Native Heap 27293 27056 196 3695 38144 30571 7572 Dalvik Heap 12776 12416 336 1993 18601 12473 6128 Dalvik Other 1737 1736 0 2 Stack 36 36 0 0 Ashmem 4390 4372 0 0 Other dev 30 4 20 0 .so mmap 13517 6220 2684 2625 .apk mmap 4083 72 2668 6316 .ttf mmap 510 0 452 0 .dex mmap 53489 24080 26868 6232 .oat mmap 2094 0 532 0 .art mmap 5876 5264 216 12 Other mmap 6507 4 6220 0 EGL mtrack 28021 28021 0 0 GL mtrack 26319 26319 0 0 Unknown 2448 2380 68 415 TOTAL 210416 137980 40260 21290 56745 43044 13700 App Summary Pss(KB) ------ Java Heap: 17896 Native Heap: 27056 Code: 63576 Stack: 36 Graphics: 54340 Private Other: 15336 System: 32176 TOTAL: 210416 TOTAL SWAP PSS: 21290 Objects Views: 681 ViewRootImpl: 3 AppContexts: 7 Activities: 1 Assets: 5 AssetManagers: 3 Local Binders: 151 Proxy Binders: 53 Parcel memory: 30 Parcel count: 121 Death Recipients: 2 OpenSSL Sockets: 5 WebViews: 0 SQL MEMORY_USED: 1105 PAGECACHE_OVERFLOW: 822 MALLOC_SIZE: 117
可以看到这块内存主要字段有pss,private。我们从上往下看。
pss total,就对应我们上一节中提到的pss,它包含了应用自己的内存,还包含了共享(或跨进程)使用的内存。
相应的private dirty就表示,就是独自占用的脏页的内存值,脏页在linux里就表示高速缓存(在物理内存中)中被修改的内存页。相反private clean就表示高速缓存中未被修改的页。
swap内存,因为内存缓存机制,会基于最近最少使用的缓存原则,将内存中长时间不运行的数据,缓存到硬盘中,这部分数据到了硬盘中,swap之后的这部分内存称为虚拟内存,在需要使用的时候,才会从硬盘中读取出来。
所以实际上,我们就把private相关的值就表示应用本身的内存占用情况,相应的pss则增加了共享库内存的内存使用。
除了这块内存参数以外,还有heap size、heap alloc 和 heap free。
heap alloc表示我们在分配的内存大小,heap free就表示空闲的内存大小。heap size则表示最大可分配的内存大小,相当于heap alloc 和 heap free的和。
我们在看一下每个内存的分类情况:
Dalvik Heap:Dalvik虚拟机分配的内存。
Native Heap:本地代码申请的内存。
.so mmap 、.dex mmap … mmap 映射本地或虚拟机代码到使用的内存中。
Unknown 无法归类的其他项。主要包括大部分的本地分配。
App summary中内存,则统计的都是private的相关内存,其中包括了:
Java Heap java的堆内存
Native Heap 本地代码的内存
Code 代码申请的内存
Stack 栈内存
Graphics 物理内存
Private Other 其他内存
System 系统内存
Objects 就包含了android中所使用的对象了,ViewRootImpl用于分析window的数量。Activities则表示activity的数量Proxy Binders,则表示本地建立binder 的数量,WebViews则表示使用webview的数量,均是发生内存泄漏的高频区,利于分析。
SQL,则是数据库使用的内存情况。
更多相关文章
- 箭头函数的基础使用
- NPM 和webpack 的基础使用
- Python list sort方法的具体使用
- 【阿里云镜像】使用阿里巴巴DNS镜像源——DNS配置教程
- Android是怎么启动的-[Android取经之路]
- android 3.0中加快启动模拟器
- Android中使用ViewPager制作广告栏滚屏效果
- Android(安卓)下使用 JSON 实现 HTTP 请求
- 一定要注意 Android(安卓)内存泄漏问题