perf top 显示 [ksoftirqd] 高占比时的 softnet_stat / netdev_budget 调优

4次阅读

perf top中[ksoftirqd]占比高通常源于网络软中断处理瓶颈,需通过/proc.net/softnet_stat分析dropped和time_squeeze字段判断是否因netdev_budget过小、RSS不均或NAPI未启用导致。

perf top 显示 [ksoftirqd] 高占比时的 softnet_stat / netdev_budget 调优

perf top 看到 [ksoftirqd] 占比高,先确认是不是软中断瓶颈

这通常不是 CPU 被“占满”了,而是网络软中断(NET_RX)在 ksoftirqd 线程里持续被唤醒、处理不过来。关键要区分:是收包太快(网卡 flood),还是单核处理能力不足(如 RSS 未开启或不均),或是 net.core.netdev_budget 设置过小导致每次只处理少量包就让出 CPU,引发高频调度开销。

检查 softnet_stat 判断是否丢包和 backlog 积压

/proc/net/softnet_stat 每行对应一个 CPU 的软中断统计,用十六进制解析前两个字段:

  • 第 1 字段(processed):该 CPU 上成功入队并处理的包数
  • 第 2 字段(dropped):因 input_pkt_queue 满或内存不足被丢弃的包数 —— 若持续增长,说明软中断处理速度跟不上入队速度
  • 第 3 字段(time_squeeze):表示一次软中断上下文中,因超时(默认 2 jiffies)提前退出,被迫下次再处理 —— 高值直接指向 netdev_budget 过小或单次处理耗时过高

例如:echo "0x$(awk 'NR==1 {print $1}' /proc/net/softnet_stat | cut -d' ' -f1)" | bc 查当前 CPU 的 processed;重复执行对比增速,若 time_squeeze 增速 > processed,基本可断定预算不足。

netdev_budget 不是越大越好,需结合 NAPI 和中断合并调

net.core.netdev_budget 控制每次软中断上下文最多处理多少个包。默认 300,太小 → 频繁重调度 ksoftirqd;太大 → 单次处理太久,影响实时任务响应,还可能加剧 cache miss。

  • 建议从 600 开始试,逐步加到 1200,观察 time_squeeze 是否归零、perf top[ksoftirqd] 占比是否下降
  • 必须同步打开网卡的 NAPI 和中断合并(如 ethtool -C eth0 rx on tx on),否则增大 budget 只会让单核更忙,不解决根本问题
  • 多队列网卡务必确认 RSS 已启用且 flow hash 均匀(ethtool -x eth0),否则所有包都砸向 CPU 0,调 budget 没用

真正卡住时,别只盯 budget,先看网卡侧配置和流量特征

很多 case 最终发现是硬件或驱动层限制:比如某 Mellanox CX4 卡在 LRO 启用时,软中断处理路径变长,即使 budget=1200 仍大量 time_squeeze;又或者 udp 小包 flood 下,skb 分配开销远超处理逻辑本身。

  • cat /sys/class/net/eth0/device/msi_irqs/* 确认每个 RX 队列绑定了哪个 CPU,再用 perf record -e irq:softirq_entry --Filter "vec==3" -C 0(vec=3 是 NET_RX)抓 CPU 0 的软中断触发频次
  • 对比 /proc/interrupts 中各 RX 队列中断分布,若严重不均,优先调 sudo ethtool -X eth0 equal 8 或手动设置 flow indirection table
  • net.core.netdev_max_backlog 要 ≥ netdev_budget,否则新包直接进 drop 路径

budget 调优只是软中断流水线中的一环,容易忽略的是:网卡 ring buffer 深度、driver 的 poll 效率、甚至 CPU frequency scaling 导致的单周期吞吐波动 —— 这些都会让同样的 budget 值在不同机器上表现迥异。

text=ZqhQzanResources