lmkd mem_pressure计算与作用

Android Q以后,google推荐使用lmkd,lmkd其中一种工作模式是根据内存压力去kill进程.

https://source.android.google.cn/devices/tech/perf/lmkd文档中:

mem_pressure = 内存使用量/RAM_and_swap 使用量(以百分比的形式表示)

具体到代码中:

   if ((mem_usage = get_memory_usage(&mem_usage_file_data)) < 0) {
        goto do_kill;
    }
    if ((memsw_usage = get_memory_usage(&memsw_usage_file_data)) < 0) {
        goto do_kill;
    }

    // Calculate percent for swappinness.
    mem_pressure = (mem_usage * 100) / memsw_usage;
    //添加log,能够查看内存压力等级
    ALOGI("mem_usage = %lld KB memsw_usage = %lld KB  mem_pressure  =  %lld " ,mem_usage/1024 , memsw_usage /1024,mem_pressure);
    if (enable_pressure_upgrade && level != VMPRESS_LEVEL_CRITICAL) {
        // We are swapping too much.
        if (mem_pressure < upgrade_pressure) {
            level = upgrade_level(level);
            if (debug_process_killing) {
                ALOGI("Event upgraded to %s", level_name[level]);
            }
        }
    }

可以看到

mem_pressure = (mem_usage * 100) / memsw_usage;
mem_usage = get_memory_usage(&mem_usage_file_data)
memsw_usage = get_memory_usage(&memsw_usage_file_data)

#define MEMCG_MEMORY_USAGE "/dev/memcg/memory.usage_in_bytes"
#define MEMCG_MEMORYSW_USAGE "/dev/memcg/memory.memsw.usage_in_bytes"

从代码中看到查看到是去读取两个节点.这两个节点存储的数据的含义就是:

1.内存使用量

2.RAM_and_swap 使用量

我们具体去cat一下并且计算开机后的内存压力.

E:\02_Project>adb shell cat /dev/memcg/memory.usage_in_bytes
568688640

E:\02_Project>adb shell cat /dev/memcg/memory.memsw.usage_in_bytes
762757120

mem_pressure = 568688640*100/762757120 = 74.5

即现在样机的内存压力为74.5.

如果使用apk,那么zram会增加.mem_pressure的数值会变小.

mem_pressure的数值与以下系统属性有关.

    ro.lmk.low=1001\
    ro.lmk.medium=800\
    ro.lmk.critical=0\
    ro.lmk.upgrade_pressure=40\
    ro.lmk.downgrade_pressure=60\

从代码可以看到:

if (mem_pressure < upgrade_pressure) {
            level = upgrade_level(level);
            if (debug_process_killing) {
                ALOGI("Event upgraded to %s", level_name[level]);
            }
        }

 if (mem_pressure > downgrade_pressure) {
            if (debug_process_killing) {
                ALOGI("Ignore %s memory pressure", level_name[level]);
            }
            return;
        } else if (level == VMPRESS_LEVEL_CRITICAL && mem_pressure > upgrade_pressure) {
            if (debug_process_killing) {
                ALOGI("Downgrade critical memory pressure");
            }
            // Downgrade event, since enough memory available.
            level = downgrade_level(level);
        }

如果
mem_pressure<40 ,内存压力等级升级.
如果
mem_pressure > 60,内存压力等级降级

压力等级为:

enum vmpressure_level {
    VMPRESS_LEVEL_LOW = 0,
    VMPRESS_LEVEL_MEDIUM,
    VMPRESS_LEVEL_CRITICAL,
    VMPRESS_LEVEL_COUNT
};

其中:

level与oomadj有对应关系.

 /* By default disable low level vmpressure events */
    level_oomadj[VMPRESS_LEVEL_LOW] =
        property_get_int32("ro.lmk.low", OOM_SCORE_ADJ_MAX + 1);
    level_oomadj[VMPRESS_LEVEL_MEDIUM] =
        property_get_int32("ro.lmk.medium", 900);
    level_oomadj[VMPRESS_LEVEL_CRITICAL] =
        property_get_int32("ro.lmk.critical", 0);

根据我们的配置:

ro.lmk.low = 1001

ro.lmk.medium = 800
ro.lmk.critical = 0

所以

level_oomadj[VMPRESS_LEVEL_LOW] =1001
level_oomadj[VMPRESS_LEVEL_MEDIUM] =800
level_oomadj[VMPRESS_LEVEL_CRITICAL] =0

下面是kill进程

if (low_ram_device) {
        /* For Go devices kill only one task */
        if (find_and_kill_process(level_oomadj[level]) == 0) {
            if (debug_process_killing) {
                ALOGI("Nothing to kill");
            }
        } else {
            meminfo_log(&mi);
        }
    }


level_oomadj[level]=1001/800/0

这里前面计算的level的等级会转换为oom_adj=1001/800/0

 接下来会到:

 

retry:
    for (i = OOM_SCORE_ADJ_MAX; i >= min_score_adj; i--) {
        struct proc *procp;

        while (true) {
            procp = kill_heaviest_task ?
                proc_get_heaviest(i) : proc_adj_lru(i);

            if (!procp)
                break;

            killed_size = kill_one_process(procp, min_score_adj);
            if (killed_size >= 0) {
#ifdef LMKD_LOG_STATS
                if (enable_stats_log && !lmk_state_change_start) {
                    lmk_state_change_start = true;
                    stats_write_lmk_state_changed(log_ctx, LMK_STATE_CHANGED,
                                                  LMK_STATE_CHANGE_START);
                }
#endif
                break;
            }
        }
        if (killed_size) {
            break;
        }
    }

 

killed_size = kill_one_process(procp, min_score_adj);
kill_one_process中最终会调用:

 r = kill(pid, SIGKILL);杀掉指定pid进程.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值