1130 字
6 分钟
应用绑核简介

绑核能够比较好的隔离CPU资源,减少上下文切换,提高应用的性能。事实上,这是FPGA进行onload之前需要做的事情。

Sysjitter#

Sysjitter工具用于衡量系统产生的抖动程度,以及这些抖动对用户级进程的影响。该工具会在每个处理器核心上运行一个线程,当该线程从核心中移除后,工具会记录其持续的时间。地址

Terminal window
./sysjitter --runtime 10 200 | column -t
core_i: 0 1 2 3
threshold(ns): 200 200 200 200
cpu_mhz: 3215 3215 3215 3215
runtime(ns): 9987653973 9987652245 9987652070 9987652027
runtime(s): 9.988 9.988 9.988 9.988
int_n: 10001 10130 10012 10001
int_n_per_sec: 1001.336 1014.252 1002.438 1001.336
int_min(ns): 1333 1247 1299 1446
int_median(ns): 1390 1330 1329 1470
int_mean(ns): 1424 1452 1452 1502
int_90(ns): 1437 1372 1357 1519
int_99(ns): 1619 5046 2392 1688
int_999(ns): 5065 22977 15604 3694
int_9999(ns): 31260 39017 184305 36419
int_99999(ns): 40613 45065 347097 49998
int_max(ns): 40613 45065 347097 49998
int_total(ns): 14244846 14719972 14541991 15031294
int_total(%): 0.143 0.147 0.146 0.150
字段描述
threshold (ns)忽略所有持续时间少于此时间的中断。
cpu_mhzCPU 速度
runtime (ns)sysjitter 的运行时间 - 以纳秒为单位
runtime (s)sysjitter 的运行时间 - 以秒为单位
int_n用户线程被中断的次数
int_n_per_sec每秒中用户线程被中断的次数
int_min (ns)由于中断导致用户线程被暂停的最低时间长度
int_median (ns)由于中断导致用户线程等待的时间中位数
int_mean (ns)由于中断导致用户线程的占用时间延长
int_90 (ns)90%分位数值
int_99 (ns)99%分位数值
int_999 (ns)99.9%的分位数值
int_9999 (ns)99.99%的分位数值
int_99999 (ns)99.999%的分位数值
int_max (ns)用户线程所占用的时间最大值
int_total (ns)未处理用户线程的总时间
int_total (%)int_total (ns) 占总运行时间的百分比

隔离核心的基本设置#

BIOS#

关闭CPU C-States和P-States,禁用超线程。

修改内核启动参数#

/etc/default/grub
GRUB_CMDLINE_LINUX="isolcpus=1-5 nohz_full=1-5 rcu_nocbs=1-5"

修改后更新GRUB并重启:

Terminal window
sudo update-grub # Ubuntu/Debian
# 或 sudo grub2-mkconfig -o /boot/grub2/grub.cfg # CentOS/RHEL
sudo reboot

处理硬件中断#

系统默认会使用 irqbalance 服务在所有 CPU 上负载均衡硬件中断。这会破坏设置好的核心隔离。

关闭irqbalance#

Terminal window
sudo systemctl stop irqbalance
sudo systemctl disable irqbalance

手动绑定硬件中断到其他核心#

Terminal window
# 设置新中断的默认亲和性
echo f | sudo tee /proc/irq/default_smp_affinity
# 遍历现有的所有硬件中断,强制绑定到 0-3 核
for irq in $(ls /proc/irq/ | grep -E '^[0-9]+'); do
echo f | sudo tee /proc/irq/$irq/smp_affinity 2>/dev/null
done

或者设置:

Terminal window
for irq_dir in /proc/irq/[0-9]*; do
irq=$(basename $irq_dir)
# 尝试将中断绑定到 0-63 核心 (过滤掉错误输出,因为某些特殊中断无法更改亲和性)
sudo sh -c "echo '0-63' > $irq_dir/smp_affinity_list" 2>/dev/null
done

驱逐内核工作队列#

内核的 kworker 线程会产生软中断。必须将未绑定的工作队列限制在管家核心上:

Terminal window
# 将 0-3 核的十六进制掩码 (f) 写入工作队列配置
echo f | sudo tee /sys/devices/virtual/workqueue/cpumask

观测结果#

观测核心中断类型#

cat << 'EOF' > watch_isol_irq.sh
#!/bin/bash
# 检查是否传入了参数
if [ -z "$1" ]; then
echo "用法: $0 <起始核心>-<结束核心> 或 $0 <单个核心>"
echo "示例: $0 64-70"
echo " $0 64"
exit 1
fi
# 解析输入参数 (支持 64-70 或 64 格式)
IFS='-' read -r start_cpu end_cpu <<< "$1"
# 如果没有输入结束核心,则起始和结束相同(单核模式)
[ -z "$end_cpu" ] && end_cpu=$start_cpu
# 将解析出的 start 和 end 传给 awk
awk -v start="$start_cpu" -v end="$end_cpu" '
NR==1 {
printf "%-10s", "IRQ"
for(i=1; i<=NF; i++) {
if ($i ~ /^CPU/) {
cpu_num = substr($i, 4) + 0
if (cpu_num >= start && cpu_num <= end) {
target_cols[i+1] = 1
printf "%10s", $i
}
last_cpu_col = i+1
}
}
print " NAME"
}
NR>1 {
sum = 0
for (i=2; i<=last_cpu_col; i++) {
if (target_cols[i]) sum += $i
}
# 只有在这几个指定核上中断数总和大于0,才打印这一行
if (sum > 0) {
printf "%-10s", $1
for (i=2; i<=last_cpu_col; i++) {
if (target_cols[i]) printf "%10s", $i
}
desc = ""
for (i=last_cpu_col+1; i<=NF; i++) {
desc = desc " " $i
}
printf " %s\n", desc
}
}' /proc/interrupts
EOF
chmod +x watch_isol_irq.sh

通过这个脚本可以查看某个或某些核心的终端情况:

Terminal window
./watch_isol_irq.sh 64
./watch_isol_irq.sh 64-70

或者结合watch来使用:

Terminal window
watch -n 1 -d "./watch_isol_irq.sh 64-70"

观测核心上有什么程序在运行#

检查有什么程序在64核上运行:

Terminal window
ps -eLo psr,pid,tid,stat,cls,rtprio,comm | awk 'NR==1 || $1==64'

内存亲和性#

内存也需要设置亲和性,不然可能会导致内存访问延迟增加,影响性能。

Terminal window
numastat -m
numastat -p 123456
taskset -acp 123456
ps -T -p 123456 -o pid,tid,pcpu,psr,comm

查看node和cpu的关系:

Terminal window
numactl --hardware # numactl -H
cat /sys/devices/system/node/node<N>/cpulist

查看网卡的node节点:

Terminal window
cat /sys/class/net/enp161s0f0/device/numa_node
应用绑核简介
https://blog.xiaobaizhang.top/posts/bind_core/
作者
张小白
发布于
2026-08-07
许可协议
CC BY-NC-SA 4.0