在前一节中已经将原声AOSP中的LMKD所支持的可配置参数简单介绍了一遍,接下来结合工作中遇到的QCOM与MTK代码的一些改动,我先列举下不同平台的差异性:
I. 在QCOM平台(Android P)中,有三个追加属性:
ro.lmk.enhance_batch_kill
默认为false - 每次杀进程的目标根据pages_to_free变量而定;
true - 每次杀进程只杀一个(pages_to_free强制赋值为0);
关于pages_to_free的取值,在minfree模式与vmpressure模式下是不同的:
//minfree logic
pages_to_free = lowmem_minfree[lowmem_targets_size - 1] -
((other_free < other_file) ? other_free : other_file);
//vmpressure logic
pages_to_free = low_pressure_mem.max_nr_free_pages -
mi.field.nr_free_pages;
minfree的算法与之前的lowmemorykiller相似,大致意思是取minfree的最后一档的值作为目标;
vmpressure的算法则更为粗暴,取开机依赖系统在vmpressure==0时记录下的最大的一次可用内存作为目标;
if (level == VMPRESS_LEVEL_LOW) {
record_low_pressure_levels(&mi);
}
void record_low_pressure_levels(union meminfo *mi) {
if (low_pressure_mem.min_nr_free_pages == -1 ||
low_pressure_mem.min_nr_free_pages > mi->field.nr_free_pages) {
if (debug_process_killing) {
ALOGI("Low pressure min memory update from %" PRId64 " to %" PRId64,
low_pressure_mem.min_nr_free_pages, mi->field.nr_free_pages);
}
low_pressure_mem.min_nr_free_pages = mi->field.nr_free_pages;
}
/*
* Free memory at low vmpressure events occasionally gets spikes,
* possibly a stale low vmpressure event with memory already
* freed up (no memory pressure should have been reported).
* Ignore large jumps in max_nr_free_pages that would mess up our stats.
*/
if (low_pressure_mem.max_nr_free_pages == -1 ||
(low_pressure_mem.max_nr_free_pages < mi->field.nr_free_pages &&
mi->field.nr_free_pages - low_pressure_mem.max_nr_free_pages <
low_pressure_mem.max_nr_free_pages * 0.1)) {
if (debug_process_killing) {
ALOGI("Low pressure max memory update from %" PRId64 " to %" PRId64,
low_pressure_mem.max_nr_free_pages, mi->field.nr_free_pages);
}
low_pressure_mem.max_nr_free_pages = mi->field.nr_free_pages;
}
}
ro.lmk.enable_adaptive_lmk
QCOM(CAF)自由的ALMK功能,以前在kernel中的逻辑是在minfree的基础上,辅以vmpressure的值进行综合判断。此功能目前移植到了LMKD上,当然也是只作用于minfree模式。
if (use_minfree_levels) {
...
// Adaptive LMK
if (enable_adaptive_lmk && level == VMPRESS_LEVEL_CRITICAL &&
i > lowmem_targets_size-4) {
min_score_adj = lowmem_adj[i-1];
}
break;
}
ro.lmk.enable_userspace_lmk
默认false,当其为true的时候,无视kernel中lowmemorykiller是否已经启用,强制启用LMKD的逻辑。
不是很清楚QCOM为什么需要做这个属性,这个属性会造成一些混乱。因为即便属性为true,但是CONFIG_ANDROID_LOW_MEMORY_KILLER没有手动关闭的话,看代码是会出现LMKD与lowmemorykiller同时工作的情况。因此不建议使能此属性。
II. MTK平台没有添加新的属性以扩展功能,但是整合了DuraSpeed(快霸)的一些trigger代码,具体快霸还没有研究过,这里暂不评论。
如上就是LMKD目前为止所有的可配置属性,很多,而且相互之间可能有作用甚至冲突。因此在这里我列举一些我目前为止发现的一些依赖、冲突关系:
当ro.lmk.use_minfree_levels=false且 CONFIG_ANDROID_LOW_MEMORY_KILLER与 CONFIG_MEMCG 均未使能。此时系统会自动重启;
当CONFIG_MEMCG_SWAP未使能,ro.lmk.critical_upgrade,ro.lmk.upgrade_pressure与ro.lmk.downgrade_pressure均没有实际效果;
如果CONFIG_ANDROID_LOW_MEMORY_KILLER已经启用,上述所有LMKD的属性均没有实际效果;
如果ro.lmk.critical_upgrade没有配置(默认false),ro.lmk.upgrade_pressure的部分逻辑会受影响,而 ro.lmk.downgrade_pressure不受影响;
将ro.lmk.low/ro.lmk.medium/ro.lmk.critical 的值设置为1001时,该档位不会进行进程回收;
针对QCOM代码,还有如下额外的规则:
ro.lmk.enable_userspace_lmk 会强制使用LMKD,即便lowmemorykiller还在工作;
ro.lmk.enable_adaptive_lmk 与 ro.lmk.enhance_batch_kill 只会在 ro.lmk.use_minfree_levels=true时生效;
以上就是目前关于LMKD的所有介绍。后续如果有时间会再更新一节,谈谈调试过程中的一些配置建议。