cpu0 softirq异常升高问题

测试用例:在非cpu0上绑定执行两个耗cpu的进程,top -1查看系统软中断占比,发现cpu0的软中断占比升高。

原因排查:

查看/proc/softirqs,显示SCHED softirq增长很快。SCHED softirq负责负载均衡。负载均衡分为三种,周期性balance,nohz balance,new idle balance。周期性balance发生在繁忙的cpu上,nohz balance和new idle balance发生在idle cpu上。cpu0是idle的cpu,但是new idle balance一般会发生在任意cpu上,nohz balance由繁忙的cpu发起ipi,引发idle cpu的SCHED软中断。因此,这种现象符合nohz balance的情形。为了验证这一点,可以使用bpftrace探测。

#!/usr/bin/env bpftrace

kfunc:smp_call_function_single_async
{
    @cpu[args->cpu, cpu]= count();
}

args->cpu代表目标cpu,cpu代表源cpu。结果发现,目标cpu和源cpu为[0, xx]的情形很多,xx正是两个进程所绑定的cpu。如此可以确定确实是nohz balance引发的cpu0软中断升高。

nohz balance在选择目标cpu的时候会调用find_new_ilb,它会从nohz这个全局变量中从小到大找idle的cpu,cpu0首当其冲,所以nohz首选的cpu就是cpu0,如果cpu0很忙则依次往后找。

这就解释了为什么cpu0的软中断会异常升高。其实还有一个因素也导致了cpu0的软中断保持不降,那就是在cpu0做load balance的时候,因为繁忙的cpu上运行的进程是绑定在该cpu上,load balance是无效的,导致cpu0一直在做load balance却始终没有成功。这似乎也是内核需要改进的地方。

但是,在某些系统上做同样的实验得到的结果是cpu0上的软中断并没有升高。这是什么原因呢?

依照上面的排查流程发现都是一样的现象,所以cpu0确实在做软中断,只是时间似乎没有被计入。查看软中断时间计算的函数:irqtime_account_irq。该函数在两种情形下是不工作的,第一是CONFIG_IRQ_TIME_ACCOUNTING没有打开,第二是在kernel cmdline设置了tsc=noirqtime(仅限x86架构)。经排查发现,cpu0没有软中断升高现象的机器都没有打开IRQ_TIME_ACCOUNTING,所以,即便在做软中断,由于没有计入时间,top也看不到。

下面这段bpftrace代码可以验证irqtime是否计入。

#!/usr/bin/env bpftrace

kfunc:irqtime_account_irq { $val
= *kaddr("sched_clock_irqtime"); printf("probe: %s, cpu: %d, sched_clock_irqtime: %d\n", probe, cpu, $val); @[cpu]=count(); }

如果sched_clock_irqtime为0或者脚本运行报找不到变量或探测点的错误代表irqtime没有计入,反之说明计入。

除了irqtime_account_irqaccount_system_time也会统计softirq的时间,因此还要看这个函数是否被调用。下面的脚本可以验证。

kprobe:account_system_index_time
/cpu==0/
{
    @[cpu, arg2] = count();
    @irqtime = hist(arg1);
}

如果arg2为3,代表有softirq计入。

抛开系统自带的统计,可以写一个脚本来统计softirq时间。

#!/usr/bin/env bpftrace

tracepoint:irq:softirq_entry {
    if (cpu == 0) {
        @start[tid] = nsecs;
    }
}
// 当 CPU 0 上的软中断处理函数结束执行时,计算耗时并更新直方图
tracepoint:irq:softirq_exit {
    if (cpu == 0) {
        $start_time = @start[tid];
        if ($start_time) {
            $duration = nsecs - $start_time;
            @latency = hist($duration / 1000);  // 转换为微秒
            delete(@start[tid]);
        }
    }
}

 

posted on 2025-02-09 13:43  半山随笔  阅读(195)  评论(0)    收藏  举报

导航