Android 内存问题与性能测试指标

1.前言

做Android开发的可能都会遇到一个问题,那就是内存泄漏(其实内存泄漏也不仅仅做Android开发,做开发基本都会遇到,最常见的就是底层开发了,像C,C++这种)。笔者这段时间被公司的一个内存问题搞得很是头大了,这里在分析内存问题的时候找到的一些资料做下记录。。

2.正文

这里描述下笔者遇到的现象:就是开机后,系统放着跑一个APP,然后过了一段时间,这里的可用内存就变为0了

正文部分皆转自 https://blog.51cto.com/12050192/1852089
一个好的性能测试指标应该满足 2 个条件:
1.对过去发生的事情做总结.
2.对未来做预期.
Settings->Memory就很好地实现了这 2 个条件:
Android 内存问题与性能测试指标_第1张图片
1.[3 hours]: 表示统计过去 3 小时 RAM 的使用情况. 使用者还可以选择 6 小时, 12 小时, 1 天.
2.[Performance]: 表示手机当前的性能情况. 这里有一套 Google 的性能评价标准.
3.[Total memory]/[Average used]/[Free]: 统计时间内 RAM 的平均使用情况. 特别是 Free, 这里也有一套 Google 的性能评价标准.
—— 这 2 个评价标准是本次的重点.
[Performance] —— 该指标的评价标准.
这是 Google 的即时指标. 仅表示打开 memory 这个页面时, 手机的 RAM 情况.
Google 的理念仍然是: RAM 不使用就是浪费, 与其浪费, 不如用来做 Cached. 所以, 当 Cached 数量少于一定数值的时候, 就表示内存不足了. 在 Kernel Space, 使用 minfree 来做衡量 Cached 是否充足的指标; 在 User Space, 使用 memFactor 来做衡量 Cached 是否充足的指标.
memFactor是这样定义的:
android/platform/frameworks/base/nougat-release/./services/core/java/com/android/server/am/ActivityManagerService.java
// Now determine the memory trimming level of background processes.

    // Unfortunately we need to start at  the back of the list to do this

    // properly.  We only do this if the number of background  apps we

    // are managing to keep around is  less than half the maximum we desire;

    // if we are keeping a good number  around, we'll let them use whatever

    // memory they want.

    final int numCachedAndEmpty =  numCached + numEmpty;

    int memFactor;

    if (numCached <= ProcessList.TRIM_CACHED_APPS

            && numEmpty <=  ProcessList.TRIM_EMPTY_APPS)  {

        if (numCachedAndEmpty <=  ProcessList.TRIM_CRITICAL_THRESHOLD)  {

            memFactor =  ProcessStats.ADJ_MEM_FACTOR_CRITICAL;

        } else if (numCachedAndEmpty  <= ProcessList.TRIM_LOW_THRESHOLD)  {

            memFactor =  ProcessStats.ADJ_MEM_FACTOR_LOW;

        } else {

            memFactor =  ProcessStats.ADJ_MEM_FACTOR_MODERATE;

        }

    } else {

        memFactor =  ProcessStats.ADJ_MEM_FACTOR_NORMAL;

    }

也就是:
Cached Process + Empty Process <= 3 个, 则认为 Critical Memory
Cached Process + Empty Process <= 5 个, 则认为 Low Memory
Cached Process <= 5 个, 而且 Empty Process <= 8 个, 则认为 Moderate Memory
其他情况则认为 Normal Memory
如果修改了 MAX_CACHED_APPS, 如上的 Threshold 也会被重新计算.
// The maximum number of cached processes we will keep around before killing them.

// NOTE: this constant is *only* a  control to not let us go too crazy with

// keeping around processes on devices  with large amounts of RAM.  For devices  that

// are tighter on RAM, the out of memory  killer is responsible for killing background

// processes as RAM is needed, and we  should *never* be relying on this limit to

// kill them.  Also note that this limit only applies to  cached background processes;

// we have no limit on the number of  service, visible, foreground, or other such

// processes and the number of those  processes does not count against the cached

// process limit.

static final int MAX_CACHED_APPS = 32;

[Free] —— 该指标的评价标准.
这是 Google 在 M 上加入的历史指标. 该指标不仅仅计算了过去一段时间的 Free RAM 情况, 而且特别在算法上加入了 Safe RAM 对未来的手机性能做预测.
android/platform/packages/apps/Settings/nougat-release/./src/com/android/settings/applications/ProcStatsData.java
if (memInfo.hiddenAppThreshold >= realFreeRam) {

            realUsedRam = freeRam;

            realFreeRam = 0;

            baseCacheRam = (long) realFreeRam;

        } else {

            realUsedRam +=  memInfo.hiddenAppThreshold;

            realFreeRam -= memInfo.hiddenAppThreshold;

            baseCacheRam =  memInfo.hiddenAppThreshold;

        }

在这里有 2 个点需要注意:
memInfo.hiddenAppThreshold. 这是 ADJ=9 对应的水位. 也就是如下的 55296 x 4K = 216M

adb shell cat /sys/module/lowmemorykiller/parameters/minfree
18432,23040,27648,32256,55296,80640
realFreeRam. 它包括 4 个部分, 分别是 Free + Cached + Buffer – Mapped.

如果统计得到的 realFreeRam 多于216M, 就在 realFreeRam 中扣除 216M, 获得的就是 App 可以使用的 Free RAM.
如果统计得到的 realFreeRam 少于216M, 那么表示 safe 空间已经被用完, App 可以使用的 Free RAM 就是 0.
会有这样的声音: 当 Free 为 0 时, 手机还是可以正常运行啊? 这个数据是不是错误的?
Google 之所以设计这个算法, 是因为有这样一个事实: 当 LMK 杀到 ADJ<9 的进程后, 手机性能会开始下降. 一开始并不明显, 但随着使用时间的增加, 下降会越来越明显, 越来越快.
所以 Google 使用 ADJ=9 的 minfree 做 Safe RAM, 是有价值并且很明智的.
对于使用者, 通过这个指标, 可以很简单知道自己的操作习惯对手机性能的影响.
因为这套指标会让数据变得很不漂亮, 很多产品会排斥. 但是作为 PM, 这套指标会让你的产品变得更 safe.
为了数据漂亮, 减少 minfree 会是一个做法. 但是另一个事实是, 调低水位, 会让 RAM 变得紧张, 增加 swap, 从而使得手机变慢. 如果使用的 eMMC 性能并不好, 请不要这样做. 增加 RAM, 减少预置功能, 积极做进程清理才是王道.

你可能感兴趣的:(android)