栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > Java

Android 内存分析

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android 内存分析

一、检查meminfo

console:/ # cat /proc/meminfo                                                 

MemTotal:        1892784 kB

MemFree:          281508 kB

MemAvailable:    1089928 kB

Buffers:           13740 kB

Cached:           841000 kB

SwapCached:            0 kB

Active:           518860 kB

Inactive:         734844 kB

Active(anon):     401492 kB

Inactive(anon):     4824 kB

Active(file):     117368 kB

Inactive(file):   730020 kB

Unevictable:         256 kB

Mlocked:             256 kB

SwapTotal:             0 kB

SwapFree:              0 kB

Dirty:                52 kB

Writeback:             0 kB

AnonPages:        399252 kB

Mapped:           257672 kB

Shmem:              7368 kB

Slab:             108576 kB

SReclaimable:      40048 kB

SUnreclaim:        68528 kB

KernelStack:       23232 kB

PageTables:        27188 kB

NFS_Unstable:          0 kB

Bounce:                0 kB

WritebackTmp:          0 kB

CommitLimit:      946392 kB

Committed_AS:   56310412 kB

VmallocTotal:   258998208 kB

VmallocUsed:      108496 kB

VmallocChunk:   258743780 kB

Meminfo里面列出来很多项,只需要关注如下几条:

MemTotal: 总内存大小

MemFree: 可以直接使用的空闲的内存大小

MemAvailable: 可以使用的内存,包括MemFree和Cached/Buffers/Slab中可以回收的部分。

Buffers: 直接读写的块设备和文件系统元数据(如super block)所使用的内存。

Cached: 从磁盘读取的文件内容的缓存大小,另外也包含了Shmem内存页

Active(anon):匿名页内存,主要是用户模式下的堆、栈,以及shmem,最近访问过

Inactive(anon):匿名页内存,主要是用户模式下的堆、栈,以及shmem,最近没有访问过

Active(file):基于文件的内存页,包含cache和buffer,但是不包含Shmem内存页,最近访问过

Inactive(file): 基于文件的内存页,包含cache和buffer,但是不包含Shmem内存页,最近没有访问过

AnonPages:匿名页内存,但是不包括Shmem 。所以AnonPages大约等于Active(anon) + Inactive(anon) - Shmem

Mapped: 设备和文件等映射的大小,共享内存、可执行程序的文件、动态库、mmap的文件等都统计在这里

Slab: slab 分配器分配的内存,主要是内核中使用

SReclaimable:slab中可回收的内存。

SUnreclaim:slab中不可回收的内存。

如果机器在运行的过程中MemAvailable持续减小,就可以怀疑系统中存在内存泄漏。但是并不是MemAvailable减小就一定存在内存泄漏,还要进一步分析减少的内存被什么占用了。如果Active(anon)+Inactive(anon)所占用的内存增加,说明用户进程占用的内存增加。如果SUnreclaim所占用的内存增加,说明kernel占用的内存增加。知道了减少的内存是被用户进程还是kernel占用之后,要分析是哪个用户进程或内核哪部分占用了内存。

二、用户进程占用内存增加

用户进程的内存页分为两种:基于文件的内存页和匿名内存页。

  1. 进程的可执行文件、动态库、程访问的文件占用的内存,都是基于文件的内存页,这些都会统计进cache和Active(file)/ Inactive(file)中。
  2. 用户进程的堆和栈属于匿名内存页,统计在AnonPages和Active(anon)/Inactive(anon)中。
  3. 还有有一个比较特殊的内存: shmem,它是通过tmpfs文件系统来实现的,所以它占用的内存会被统计在cache中,但是它又没有磁盘介质,所以它占用的内存实际上是属于匿名内存。所以Shmem被统计在Inactive(anon)/ Active(anon)中,而没有被统计在Inactive(file)/ Active(file)中

Active(file)/ Inactive(file)中的内存是可回收的,当系统内存不足时,系统会将这部分内存释放掉,所以这部分内存不会存在内存泄漏。所以要判断用户进程是否有内存泄漏,我们只需要看Active(anon)/Inactive(anon)是否持续增加就可以了。一旦发现Active(anon)+Inactive(anon)持续增加,我们就可以通过dumpsys meminfo命令来检查进程所占用的内存空间。如果哪个进程有持续的内存泄漏,它占用的内存一定会持续增加,根据这个信息我们就可以找到可疑的进程,再进一步分析。

dumpsys meminfo

Applications Memory Usage (in Kilobytes):

Uptime: 702679 Realtime: 702679

Total PSS by process:

     86,379K: system (pid 1375)

     84,592K: surfaceflinger (pid 537)

     63,558K: com.android.systemui (pid 1613)

     56,996K: com.histone.postest (pid 3111 / activities)

     29,792K: zygote (pid 576)

     29,053K: com.android.launcher3ex (pid 2247 / activities)

     25,333K: com.android.phone (pid 1944)

     24,179K: com.android.inputmethod.latin (pid 3134)

     22,759K: com.android.bluetooth (pid 1787)

     21,780K: com.google.android.inputmethod.pinyin (pid 1800)

     21,446K: mm-qcamera-daemon (pid 605)

     17,518K: com.android.calculator2 (pid 2998 / activities)

     17,132K: zygote64 (pid 575)

     13,696K: com.android.chrome (pid 2963)

     13,238K: com.android.settings (pid 1823)

     10,341K: android.process.acore (pid 2131)

      9,689K: audioserver (pid 577)

      9,300K: com.android.email (pid 2565)

      8,793K: rild (pid 592)

      8,507K: .dataservices (pid 2173)

      8,494K: netmgrd (pid 663)

      8,031K: rild (pid 650)

      7,223K: ims_rtp_daemon (pid 1116)

      6,918K: cnd (pid 556)

      5,935K: imscmservice (pid 1118)

      5,810K: com.android.calendar (pid 2515)

      5,809K: android.process.media (pid 3041)

      5,758K: mm-pp-dpps (pid 549)

      5,417K: com.android.providers.calendar (pid 2551)

      5,267K: com.histone.pos.shareduserfile (pid 2777)

      5,223K: qseeproxydaemon (pid 603)

三、内核内存泄漏

内核中主要通过slab来动态分配内存。Slab分配的内存又分为SReclaimable和SUnreclaim,其中SReclaimable是可回收的,SUnreclaim是不可回收的。我们要检查内核中是否有内存泄漏,只需要检查SUnreclaim有没有持续增加即可。一旦发现SUnreclaim持续增加,我们需要检查slabinfo,

  • 打开如下内核宏

CONFIG_STACKTRACE=y

CONFIG_DEBUG_SLAB=y

CONFIG_SLABINFO=y

 增大buffer

  • 运行cat /proc/slabinfo命令,检查哪个slab持续增加

如上图,我们在海信SC60的slabinfo中发现kmalloc-8192占用的内存持续增加,所以需要对kmalloc-8192做进一步分析。

  •  运行echo 1 > /sys/kernel/slab/xxx/trace,然后dmesg,其中xxx是对应的slab名称。在dmesg中,我们可以看到相应slab申请和释放的callstack。但是这个方法有个缺点,如果slab申请和释放很频繁,dmesg log会非常多,甚至会引起系统卡死。
  •  运行cat /sys/kernel/slab/xxx/alloc_calls 

 

如上图,这个命令会把当前申请的slab的函数打印出来,同时还会打印出每个函数申请slab的次数,如上图__netdev_alloc_skb申请了192次kmalloc-8192。这里边只列出来当前申请了,还没有被释放的内存次数。我们可以观察系统在运行中,哪个函数申请slab的次数会持续增加,如果这个函数申请slab持续增加,就需要检查这个函数对应代码是否存在内存泄漏。

转载请注明:文章转载自 www.wk8.com.cn
本文地址:https://www.wk8.com.cn/it/1036297.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号