如何区分分析QEMU/KVM主机高%system与%softirq CPU占用的内核瓶颈
一、先明确两类CPU占用的内核上下文差异
%system对应常规内核态上下文,包含系统调用处理、KVM虚拟机核心逻辑(如VMExit处理、虚拟机调度)、进程管理等非中断类内核工作;%softirq对应软中断上下文,是内核为了延迟处理硬件中断而触发的后台任务,比如网络收发、定时器、块设备处理等。perf采样时会给不同上下文的函数栈打上标记,我们可以利用这一点做区分。
二、用perf过滤分离两类采样数据
1. 识别采样数据的上下文标记
先运行perf report --stdio查看原始采样结果,软中断上下文的函数栈会带有irq:前缀(比如irq:net_tx对应网络发送软中断、irq:timer对应定时器软中断),而常规%system对应的内核函数没有这个前缀。
2. 单独分析%system对应的内核函数
过滤掉所有软中断上下文的采样,只保留常规内核态数据:
perf report --stdio --filter 'not irq:*'
结合你的QEMU/KVM场景,重点关注KVM相关函数(如kvm_vcpu_run、kvm_handle_exit)、virtio设备后端处理函数(如virtio_net_handle_tx)、以及系统调用入口函数,这些是导致%system高的核心候选。
3. 单独分析%softirq对应的内核函数
只筛选软中断上下文的采样数据:
perf report --stdio --filter 'irq:*'
针对你的TCP发送负载,优先查看irq:net_tx相关的函数链,比如net_tx_action、tcp_transmit_skb的软中断分支,以及virtio网络设备的软中断处理逻辑,这些是驱动%softirq占用的关键。
三、结合QEMU进程PID缩小分析范围
既然已确认主机%system和QEMU进程的%system高度匹配,可以直接针对QEMU的PID采样,排除其他进程干扰:
perf record -p <QEMU进程PID> --all-kernel -- sleep 30
再用上述过滤命令分别分析常规内核态和软中断的函数开销,结果会更精准。
四、KVM场景的针对性排查点
针对虚拟机TCP发送的负载,额外关注以下内核逻辑的开销:
- VMExit处理:虚拟机触发的IO、内存操作会进入内核处理,对应
kvm_handle_exit系列函数 - Virtio网络后端:虚拟机的网络请求最终会落到主机的virtio驱动,对应
virtio_net_*系列函数 - 内存虚拟化:EPT页表维护、页故障处理等,对应
kvm_mmu_*系列函数
可以用perf script导出采样数据后统计这些函数的出现频率:
perf script | grep -E 'kvm_vcpu_run|virtio_net|kvm_handle_exit' | wc -l
内容的提问来源于stack exchange,提问作者choiyhking

