最近遇到一个Lost RAM占用内存达到1,296,701K,Free RAM只有157,924K 出现lowmom问题:
MemInfo: 43,292K slab, 114,292K shmem, 65,292K vm alloc, 12,324K page tables 5,568K kernel stack
1,572K buffers, 269,472K cached, 188,532K mapped, 75,412K free
ZRAM: 4K RAM, 520,908K swap total, 520,908K swap free
Free RAM: 157,924K
Used RAM: 591,439K
Lost RAM: 1,296,701K
可以看到,出现lowmom问题是,Used RAM并不高,和正常的相差无几。
发现问题出现时,Lost RAM异常的大,在总RAM一定的情况下,Used RAM稳定的情况下,Free RAM和Lost RAM 存在此消彼长的现象。
所以这里我将Lost RAM 统计相关的源码进行分析。
Lost RAM 统计的源码:/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
- memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
- memInfo.getKernelUsedSizeKb() - memInfo.getZramTotalSizeKb();
我们可以使用命令:adb shell "dumpsys meminfo |grep RAM "
查看正常设备设备RAM信息。
Total RAM: 2,049,328K (status moderate)
Free RAM: 1,267,152K ( 37,644K cached pss + 345,436K cached kernel + 884,072K free)
Used RAM: 487,842K ( 307,414K used pss + 180,428K kernel)
Lost RAM: 294,330K
ZRAM: 4K physical used for 0K in swap ( 520,908K total swap)
Tuning: 192 (large 512), oom 184,320K, restore limit 61,440K (high-end-gfx)
即:Lost RAM =2,049,328K-((37,644K+307,414K)-totalSwapPss)- 884,072K-345,436K-180,428K-4k =294,330K
也就是Lost RAM 统计信息中,除了totalSwapPss未在上述命令查询结果中直接显示外,其他信息直接可以使用命令查看到。
可以看到正常情况下:2049328-(37644+307414)-884072-345436-180428-4-294330= -totalSwapPss = 0.
可以看到,正常情况下totalSwapPss的值并不大。
继续看源码:
final void dumpApplicationMemoryUsage(FileDescriptor fd,
PrintWriter pw, String prefix, String[] args, boolean brief, PrintWriter categoryPw) {
...
ArrayList<ProcessRecord> procs = collectProcesses(pw, opti, packages, args);
...
long totalSwapPss = 0;
...
Debug.MemoryInfo mi = null;
for (int i = procs.size() - 1 ; i >= 0 ; i--) {
...
final long myTotalSwapPss = mi.getTotalSwappedOutPss();
synchronized (this) {
if (r.thread != null && oomAdj == r.getSetAdjWithServices()) {
// Record this for posterity if the process has been stable.
r.baseProcessTracker.addPss(myTotalPss, myTotalUss, true, r.pkgList);
}
}
if (!isCheckinRequest && mi != null) {
...
totalSwapPss += myTotalSwapPss;// 所有进程swap占用空间总和
...
}
}
}
...
}
totalSwapPss 是所有进程swap占用空间总和。再其他值都正常的情况下,Lost RAM和totalSwapPss成正比关系。
所以接下来,需要进一步取排查totalSwapPss究竟和哪个进程有关系?
排查思路:将totalSwapPss += myTotalSwapPss;// 所有进程swap占用空间总和 这一行前面打印进程号。
排查结果:totalSwapPss实际上为0,日志打印各进程的myTotalSwapPss,所以这个思路无法定位问题。所以有了下一篇:Lost RAM可能的原因