Android Lost RAM的统计方法

最近遇到一个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可能的原因

发布了142 篇原创文章 · 获赞 258 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/conconbenben/article/details/103859778