1130 字
6 分钟
应用绑核简介
绑核能够比较好的隔离CPU资源,减少上下文切换,提高应用的性能。事实上,这是FPGA进行onload之前需要做的事情。
Sysjitter
Sysjitter工具用于衡量系统产生的抖动程度,以及这些抖动对用户级进程的影响。该工具会在每个处理器核心上运行一个线程,当该线程从核心中移除后,工具会记录其持续的时间。地址
./sysjitter --runtime 10 200 | column -tcore_i: 0 1 2 3threshold(ns): 200 200 200 200cpu_mhz: 3215 3215 3215 3215runtime(ns): 9987653973 9987652245 9987652070 9987652027runtime(s): 9.988 9.988 9.988 9.988int_n: 10001 10130 10012 10001int_n_per_sec: 1001.336 1014.252 1002.438 1001.336int_min(ns): 1333 1247 1299 1446int_median(ns): 1390 1330 1329 1470int_mean(ns): 1424 1452 1452 1502int_90(ns): 1437 1372 1357 1519int_99(ns): 1619 5046 2392 1688int_999(ns): 5065 22977 15604 3694int_9999(ns): 31260 39017 184305 36419int_99999(ns): 40613 45065 347097 49998int_max(ns): 40613 45065 347097 49998int_total(ns): 14244846 14719972 14541991 15031294int_total(%): 0.143 0.147 0.146 0.150| 字段 | 描述 |
|---|---|
threshold (ns) | 忽略所有持续时间少于此时间的中断。 |
cpu_mhz | CPU 速度 |
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,禁用超线程。
修改内核启动参数
GRUB_CMDLINE_LINUX="isolcpus=1-5 nohz_full=1-5 rcu_nocbs=1-5"修改后更新GRUB并重启:
sudo update-grub # Ubuntu/Debian# 或 sudo grub2-mkconfig -o /boot/grub2/grub.cfg # CentOS/RHELsudo reboot处理硬件中断
系统默认会使用 irqbalance 服务在所有 CPU 上负载均衡硬件中断。这会破坏设置好的核心隔离。
关闭irqbalance
sudo systemctl stop irqbalancesudo systemctl disable irqbalance手动绑定硬件中断到其他核心
# 设置新中断的默认亲和性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/nulldone或者设置:
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/nulldone驱逐内核工作队列
内核的 kworker 线程会产生软中断。必须将未绑定的工作队列限制在管家核心上:
# 将 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 1fi
# 解析输入参数 (支持 64-70 或 64 格式)IFS='-' read -r start_cpu end_cpu <<< "$1"# 如果没有输入结束核心,则起始和结束相同(单核模式)[ -z "$end_cpu" ] && end_cpu=$start_cpu
# 将解析出的 start 和 end 传给 awkawk -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/interruptsEOFchmod +x watch_isol_irq.sh通过这个脚本可以查看某个或某些核心的终端情况:
./watch_isol_irq.sh 64./watch_isol_irq.sh 64-70或者结合watch来使用:
watch -n 1 -d "./watch_isol_irq.sh 64-70"观测核心上有什么程序在运行
检查有什么程序在64核上运行:
ps -eLo psr,pid,tid,stat,cls,rtprio,comm | awk 'NR==1 || $1==64'内存亲和性
内存也需要设置亲和性,不然可能会导致内存访问延迟增加,影响性能。
numastat -mnumastat -p 123456taskset -acp 123456ps -T -p 123456 -o pid,tid,pcpu,psr,comm查看node和cpu的关系:
numactl --hardware # numactl -Hcat /sys/devices/system/node/node<N>/cpulist查看网卡的node节点:
cat /sys/class/net/enp161s0f0/device/numa_node