前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PSI 与ULMK --android low memory killer

PSI 与ULMK --android low memory killer

作者头像
用户9732312
发布2022-05-13 21:35:53
2.8K0
发布2022-05-13 21:35:53
举报
文章被收录于专栏:ADAS性能优化

为了提高系统性能,Android系统中进程的匿名页、文件页按照一定的策略进行缓存,在内存紧张的时候再进行回收。但内存回收并不总是理想的,在一定条件下,为了保证系统的正常运行,会采用更加激进、直接的方式——杀进程。low memory killer(lmk)。

在android 系统中LMK经历了两次演进。

KLMK

KLMK在android中存在了很长的时间,其基本原理是基于minfree来控制kill 相关的app的相关测试。例如下一组配置,/sys/module/lowmemorykiller/parameters/minfree :15360,19200,23040,26880,34415,43737;/sys/module/lowmemorykiller/parameters/adj : 0,1,2,4,9,10. 表示当系统可用内存低于26880个page的时候杀oom_score_adj>=4的进程。

Kernel会根据vmpressure的情况产生vmpressure event.KLMK会根据不同的vmpressure事件,选择不同的档位(adj)/minfree 值来挑选APPkill来进行memory的回收。然而根据vmpressure也有不少缺点。如代码维护,由于KLMK 是android 独有的,因此linuxupstream 并不愿意维护这部分代码,因此内核4.12开始,kernel 中KLMK驱动程序。其次vmpressure+minfree+系统空余memory,不能很好的反应系统实际使用memory紧张的情况,比如,如果系统内存碎片太多,而系统freememory 很充足,但是系统使用可能也会很卡顿。如果使用KLMK就不能很好的解决该问题。而PSI(Pressure Stall Information)便能较好的处理这种情况。

PSI+ULMK

在Android10以及以后的版本,android变采用基于PSI 的ULMK

PSI 是Facebook搞的一套东西并在2018 年开源。PSI提供了一种评估系统资源压力的方法。系统有三个基础资源:CPU、Memory 和 IO.PSI 主要也是对这三种资源进行监控。

PSI 把系统缺少资源而stuck的为some 和full.

Some

Some代表至少有一个任务在一段时间内由于缺少某个资源而阻塞。为了便于表示some的严重程度用缺少资源的时间/统计时间。一个%来标识some指标。

Full

Full代表所有的非idle任务同时被阻塞. 为了便于表示full的严重程度用缺少资源的时间/统计时间。一个%来标识full指标。

一个例子

我们以Memory 的 some 和 full 来举例说明,假设在 60 秒的时间段内,系统有两个task,在 60 秒的周期内的运行情况如下图所示:

红色阴影部分表示任务由于等待Memory 资源而进入阻塞状态。TaskA 和 Task B同时阻塞的部分为full,占比16.66%;至少有一个任务阻塞(仅Task B 阻塞的部分也计算入内)的部分为some,占比 50%。

some 和 full 都是在某一时间段内阻塞时间占比的总和,阻塞时间不一定连续,如下图所示:

PSI+ULMK的实现

PSI 在task_struct 结构中加入了一个成员:PSI_flags,用于标注任务所处状态,状态定义有以下几种:

代码语言:javascript
复制
#define TSK_IOWAIT(1 << NR_IOWAIT)  // IO WAIT
#define TSK_MEMSTALL(1 << NR_MEMSTALL) //Memory stall
#define TSK_RUNNING(1 << NR_RUNNING)   //tskrunning

状态的标记主要通过函数psi_task_change,这个函数在任务每次进出调度队列时,都会被调用,从而准确标注任务状态。

kernel/sched/psi.c

system/memory/lmkd/lmkd.cpp

初始化

首先建立proc/pressure目录,然后 3 个 proc_create 函数创建了io、memory 和 cpu 三个 proc 属性文件:

代码语言:javascript
复制
proc_mkdir("pressure", NULL);     
proc_create("pressure/io", 0, NULL,&psi_io_fops);    
proc_create("pressure/memory", 0, NULL,&psi_memory_fops);   
proc_create("pressure/cpu", 0, NULL,&psi_cpu_fops);

psi_init 函数中初始化统计管理结构和更新任务的周期:

psi_period = jiffies_to_nsecs(PSI_FREQ); //默认2s

group_init(&psi_system);

我们把相关的任务组成一个group,然后针对这个任务组计算其PSI 值。当前系统只有一个PSI group:

代码语言:javascript
复制
static DEFINE_PER_CPU(struct psi_group_cpu,system_group_pcpu);
 
static struct psi_group psi_system = {
.pcpu = &system_group_pcpu,

};

如果支持cgroup(需要mount cgroup2 文件系统),那么系统中会有多个PSI group,形成层级结构。我们可以在挂载的cgroup 文件系统下面获取per-group 的 PSI 信息。

我们也可以从proc 文件系统下面获取整个系统级别的PSI 信息。Cgroup中各个分组的PSI 信息跟踪是类似的。

struct psi_group 用来定义PSI 统计管理数据,其中包括各cpu 状态、周期性更新函数、更新时间戳、以及各PSI 状态的时间记录。PSI状态一共有六种:

代码语言:javascript
复制
enum psi_states {
PSI_IO_SOME,
PSI_IO_FULL,
PSI_MEM_SOME,
PSI_MEM_FULL,
PSI_CPU_SOME,
/* Only per-CPU, to weigh the CPU in the global average: */
PSI_NONIDLE,
NR_PSI_STATES,
};

ULMK 注册PSI

当ULMK 后台进程起来的时候,会首先注册some/full PSI 事件。

代码语言:javascript
复制
static struct psi_thresholdpsi_thresholds[VMPRESS_LEVEL_COUNT] = {
    { PSI_SOME, 70},    /* 70ms out of 1sec for partialstall */
    { PSI_SOME, 100},   /* 100ms out of 1sec for partialstall */
{ PSI_FULL, 70 },    /* 70ms out of 1sec for complete stall */
}
static bool init_psi_monitors() {
….
if(!init_mp_psi(VMPRESS_LEVEL_LOW, use_new_strategy)) {
    }
    if (!init_mp_psi(VMPRESS_LEVEL_MEDIUM,use_new_strategy)) {
    }
    if (!init_mp_psi(VMPRESS_LEVEL_CRITICAL,use_new_strategy)) {
    }
    if(!init_mp_psi(VMPRESS_LEVEL_SUPER_CRITICAL, use_new_strategy)) {
    } …..
}

PSI event

PSI 收到ULMK的注册后,会创建psimon kworker。Psimon kworker 会根据ULMK 注册的信息周期性的起来计算当前系统memroy的压力情况,当memory的压力值达到设定的阈值时,psimon 变trigger PSI event。

代码语言:javascript
复制

另一侧ULMK 会监听PSI event。当PSI event 发生时,ULMK 会epoll当前

的PSI event,然后根据PSI event的采用相关的策略。

周期性统计

更新统计数据的函数update_stats,主要有两步:

第一步get_recent_times,对每个 cpu更新各状态的时间并统计各状态系统总时间;

第二步calc_avgs,更新每个状态的10s、60s、300s 三个间隔的时间占比。

计算一个 PSIgroup 的 PS I值的过程示意图如下所示:

Memory Stall

哪些情况被认为是Memorystall?

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-04-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Android性能优化 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • KLMK
  • PSI+ULMK
    • Some
      • Full
        • 一个例子
        • PSI+ULMK的实现
          • 初始化
            • ULMK 注册PSI
              • PSI event
                • 周期性统计
                • Memory Stall
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档