内存管理-44-PSI-理论

基于msm-5.4


一、psi.txt翻译

翻译: msm-5.4/Documentation/accounting/psi.rst

==================================
PSI - 压力失速信息(Pressure Stall Information)
=================================

:日期:2018 年 4 月
:作者:Johannes Weiner <hannes@cmpxchg.org>

当 CPU、内存或 IO 设备发生争用时,工作负载会出现延迟峰值、吞吐量损失,并面临 OOM kill的风险。

如果没有准确衡量此类争用,用户就不得不要么谨慎行事,未充分利用硬件资源,要么孤注一掷,并经常遭受过度使用导致的中断。

psi 功能可识别和量化此类资源紧缩造成的中断及其对复杂工作负载甚至整个系统的时间影响。

准确衡量资源匮乏造成的生产力损失有助于用户根据工作负载需求调整硬件工作负载大小,或配置硬件。

由于 psi 实时汇总这些信息,因此可以使用诸如负载削减、将作业迁移到其他系统或数据中心,或策略性地暂停或终止低优先级或可重新启动的批处理作业等技术动态管理系统。

这样可以最大限度地提高硬件利用率,而不会牺牲工作负载健康或冒着 OOM kill等重大中断的风险。


压力接口
===================

每个资源的压力信息通过 /proc/pressure/ 中的相应文件导出 - cpu、memory 和 io。

CPU 的格式如下:

some avg10=0.00 avg60=0.00 avg300=0.00 total=0

内存和 IO 的格式如下:

some avg10=0.00 avg60=0.00 avg300=0.00 total=0
full avg10=0.00 avg60=0.00 avg300=0.00 total=0

"some"行表示至少一些任务在给定资源上停滞的时间份额。

"full" 行表示所有非空闲任务在给定资源上同时停滞的时间份额。在此状态下,实际的 CPU 周期将被浪费,并且在此状态下花费较长时间的工作负载被视为处于抖动状态。这会严重影响性能,将这种情况与某些任务停滞但 CPU 仍在进行生产性工作的状态区分开来很有用。因此,在停滞状态的这个子集中花费的时间被单独跟踪并导出到"full"平均值中。

比率(以 % 为单位)被跟踪为十秒、六十秒和三百秒窗口内的近期趋势,这可以洞察短期事件以及中期和长期趋势。total 绝对停顿时间(以 us 为单位)也被跟踪和导出,以便检测不一定会对时间平均值造成影响的延迟峰值,或者在自定义时间范围内平均趋势。


监控压力阈值
====================================

用户可以注册触发器,并在资源压力超过特定阈值时使用 poll() 唤醒。

触发器描述特定时间窗口内的最大累积停顿时间,例如,任何 500 毫秒窗口内的总停顿时间为 100 毫秒,以生成唤醒事件。

要注册触发器,用户必须打开 /proc/pressure/ 下表示要监控的资源的 psi 接口文件,并写入所需的阈值和时间窗口。打开的文件描述符应该用于等待使用 select()、poll() 或 epoll() 的触发事件。使用以下格式:

<some|full> <stall amount in us> <time window in us>

例如,将“some 150000 1000000”写入 /proc/pressure/memory 会为 1 秒时间窗口内测量的部分内存停顿添加 150ms 阈值。将“full 50000 1000000”写入 /proc/pressure/io 会为 1 秒时间窗口内测量的完整 io 停顿添加 50ms 阈值。

可以在多个 psi 指标上设置触发器,并且可以为同一 psi 指标指定多个触发器。但是,对于每个触发器,都需要一个单独的文件描述符才能将其与其他触发器分开轮询,因此,即使打开相同的 psi 接口文件,也应该为每个触发器进行单独的 open() 系统调用。对具有现有 psi 触发器的文件描述符的写入操作将失败,并出现 EBUSY。

仅当系统进入所监控 psi 指标的失速状态时,监视器才会激活,退出失速状态时监视器就会停用。当系统处于失速状态时,psi 信号的增长以每个跟踪窗口 10 次的速率进行监控。

内核接受的窗口大小范围为 500ms 到 10s,因此最小监控更新间隔为 50ms,最大为 1s。设置最小限制是为了防止轮询过于频繁。最大限制被选择为一个足够高的数字,在此之后很可能不需要监视器,而可以使用 psi 平均值。

激活后,psi 监视器至少在一个跟踪窗口的持续时间内保持活动状态,以避免在系统进入和退出失速状态时重复激活/停用。

每个跟踪窗口向用户空间发送的通知频率限制为一次。

当用于定义触发器的文件描述符关闭时,触发器将取消注册。


用户空间监视器使用示例
==================================

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <poll.h>
#include <string.h>
#include <unistd.h>

/* 使用 1s 的跟踪窗口大小和 150ms 的阈值来监控内存部分停顿 */
int main() {
    const char trig[] = "some 150000 1000000";
    struct pollfd fds;
    int n;

    fds.fd = open("/proc/pressure/memory", O_RDWR | O_NONBLOCK);
    if (fds.fd < 0) {
        printf("/proc/pressure/memory open error: %s\n", strerror(errno));
        return 1;
    }
    fds.events = POLLPRI;

    if (write(fds.fd, trig, strlen(trig) + 1) < 0) {
        printf("/proc/pressure/memory write error: %s\n", strerror(errno));
        return 1;
    }

    printf("waiting for events...\n");
    while (1) {
        n = poll(&fds, 1, -1);
        if (n < 0) {
            printf("poll error: %s\n", strerror(errno));
            return 1;
        }
        if (fds.revents & POLLERR) {
            printf("got POLLERR, event source is gone\n");
            return 0;
        }
        if (fds.revents & POLLPRI) {
            printf("event triggered!\n");
        } else {
            printf("unknown event received: 0x%x\n", fds.revents);
            return 1;
        }
    }

    return 0;
}


Cgroup2 接口
==================

在具有 CONFIG_CGROUP=y 内核和已安装 cgroup2 文件系统的系统中,还会跟踪分组到 cgroups 中的任务的压力失速信息。cgroupfs 挂载点中的每个子目录都包含 cpu.pressure、memory.pressureio.pressure 文件;格式与 /proc/pressure/ 文件相同。

可以像系统范围的监视器一样指定和使用每个 cgroup psi 监视器。

 

posted on 2024-11-28 09:18  Hello-World3  阅读(27)  评论(0编辑  收藏  举报

导航