系统iowait和线程的iowait

系统iowait和线程的iowait

系统iowait时间统计

在系统时钟中断时,会调用account_process_tick,如果是user tick,则增加user time;否则如果current线程不是idle,则增加system time;否则增加idle时间,idle可以再分为iowait和纯粹的idle,如果当前cpu的runqueue的nr_iowait大于0,则增加iowait time,否则增加idle time

void account_process_tick(struct task_struct *p, int user_tick)
{
    u64 cputime, steal;
    struct rq *rq = this_rq();

    if (vtime_accounting_cpu_enabled())
        return;

    if (sched_clock_irqtime) {
        irqtime_account_process_tick(p, user_tick, rq, 1);
        return;
    }

    cputime = TICK_NSEC;
    steal = steal_account_process_time(ULONG_MAX);

    if (steal >= cputime)
        return;

    cputime -= steal;

    if (user_tick)
        account_user_time(p, cputime);
    else if ((p != rq->idle) || (irq_count() != HARDIRQ_OFFSET))
        account_system_time(p, HARDIRQ_OFFSET, cputime);
    else
        account_idle_time(cputime);
}
void account_idle_time(u64 cputime)
{
    u64 *cpustat = kcpustat_this_cpu->cpustat;
    struct rq *rq = this_rq();

    if (atomic_read(&rq->nr_iowait) > 0)
        cpustat[CPUTIME_IOWAIT] += cputime;
    else
        cpustat[CPUTIME_IDLE] += cputime;
}

线程的iowait

io_schedule_timeout/io_schedule函数里先调用io_schedule_prepare,在这个函数里将当前的task的in_iowait设置为1.

在update_stats_enqueue_sleeper判断如果task的in_iowait为1,则statistics.iowait_sum(可以在/proc/pid/sched里找到这个值)累加上这次iowait的时间delta,这里有个sched_stat_iowait trace,所以会记录一条sched_stat_iowait的trace,这条trace记录了这个线程这次iowait的时间delta。

static inline void
update_stats_enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se)
    sleep_start = schedstat_val(se->statistics.sleep_start);
    block_start = schedstat_val(se->statistics.block_start);
    if (block_start) {
        u64 delta = rq_clock(rq_of(cfs_rq)) - block_start;
        __schedstat_set(se->statistics.block_start, 0);
        __schedstat_add(se->statistics.sum_sleep_runtime, delta);
        if (tsk) {
            if (tsk->in_iowait) {
                __schedstat_add(se->statistics.iowait_sum, delta);
                __schedstat_inc(se->statistics.iowait_count);
                trace_sched_stat_iowait(tsk, delta);
            }

            trace_sched_stat_blocked(tsk, delta);

系统iowait和线程的iowait两者的区别

系统的iowait是全局的,针对CPU而言,如果此CPU是在运行idle线程,则增加idle时间;如果是运行的idle线程,但是它的runqueue上有在等待io的线程,则是iowait,增加iowait的时间,此iowait时间在top cmd结果(wa or iowait)里会呈现;

线程的iowait是此线程因等待IO而调用了io_schedule_timeout/io_schedule,等待IO完成的这一段时间是该线程这次的iowait时间,sched_stat_iowait trace event里会呈现此时间。

 

posted @ 2023-04-15 16:42  aspirs  阅读(148)  评论(0编辑  收藏  举报