Ubuntu 20.04中entry_SYSCALL_64_after_hwframe高CPU负载求助
问题分析与解决方案
核心问题定位
从perf报告来看,entry_SYSCALL_64_after_hwframe的CPU消耗核心来自sched_yield系统调用的调用链,占比超12%,最终落到任务切换的finish_task_switch环节。结合你提到的内核升级背景(linux-tools-5.15.0-69-generic),大概率是内核调度器在虚拟机环境下的适配问题,或是自研计算程序的调度行为触发了内核低效路径。
针对性排查与修复步骤
1. 回退内核版本验证
既然问题是升级到5.15.0-69后出现的,先回退到之前正常的内核版本确认:
- 重启虚拟机,在GRUB菜单选择Advanced options for Ubuntu,选择之前的内核版本(比如5.15.0-68或更早)
- 启动后用
perf top验证entry_SYSCALL_64_after_hwframe的CPU占比是否恢复正常 - 若恢复,可锁定旧内核:
sudo apt-mark hold linux-image-5.15.0-xx-generic linux-tools-5.15.0-xx-generic
2. 调整虚拟机CPU调度参数
VMPlayer虚拟机环境下,内核调度器可能因虚拟化层限制出现异常调度:
- 关闭虚拟机的CPU热插拔功能(VMPlayer设置 -> 处理器 -> 取消勾选"启用CPU热插拔")
- 调整虚拟机CPU的"虚拟化引擎"设置:选择"Intel VT-x/EPT或AMD-V/RVI",并勾选"性能计数器"
- 在Ubuntu虚拟机内将调度器设为
performance模式:echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
3. 排查自研程序的sched_yield调用
perf报告中sched_yield占比极高,需检查自研计算程序的调度逻辑:
- 用
perf record -g -p <程序PID>采集程序调用栈,确认sched_yield的触发点 - 若程序主动调用
sched_yield(比如线程"礼让"逻辑),尝试移除该调用,依赖内核自动调度 - 若使用线程池,检查线程数量是否超过CPU核心数,导致频繁任务切换
4. 内核参数调优
针对虚拟机环境的调度器行为,调整以下参数:
- 减少高频任务切换开销:
sudo sysctl -w kernel.sched_min_granularity_ns=1000000 sudo sysctl -w kernel.sched_wakeup_granularity_ns=1500000 - 关闭虚拟机内核tickless模式(部分虚拟化环境下会引发调度异常):
sudo sysctl -w kernel.timer_migration=0
5. 升级到最新5.15系列内核
Ubuntu 20.04的5.15内核后续版本可能修复了该问题,尝试升级:
sudo apt update && sudo apt upgrade linux-image-generic linux-tools-generic
升级后重启虚拟机,再次用perf验证CPU占比情况
内容的提问来源于stack exchange,提问作者Synopsis
相关产品推荐
相关产品推荐

