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进程.
上一篇: ZK Studio 0.9.2 发布
下一篇: 超酷的 Firefox 3.7主题