负载排查和分析二

Perf Step1 基础统计 中补充完整分析面、现象、分析工具、方法和可能原因,并对中断触发机制和关联关系做完善。以下是整理后的 完整文档


Linux 网络优化与性能分析完全指南


1️⃣ 中断与软中断基础

1.1 中断(IRQ)概念

  • 定义:CPU 在执行任务时,外设或内核事件请求 CPU 立即响应。

  • 作用:及时处理外设请求和系统事件,保证系统响应及时、稳定。

  • 触发机制

    • 外设或定时器发出信号 → 硬中断触发 CPU

    • 硬中断执行期间可能触发软中断或被内核延迟处理


1.2 硬中断(Hard IRQ)

  • 触发方式:硬件直接触发,如网卡收包、磁盘 I/O、定时器

  • 作用

    • 快速响应外设请求

    • 优先级高,必须短时间完成

  • 执行上下文:CPU 当前上下文

  • 查看方式

cat /proc/interrupts
  • 优化手段:IRQ 绑核(affinity)


1.3 软中断(Soft IRQ)

  • 触发方式:硬中断处理完成后,由内核延迟执行

  • 作用

    • 处理硬中断后的任务,如网络数据包、任务调度

    • 分发到多核,提高 CPU 利用率

  • 执行上下文:ksoftirqd 内核线程

  • 优化手段

    • RPS(Receive Packet Steering):按 CPU 分发

    • RFS(Receive Flow Steering):按流绑定 CPU

  • 查看方式

cat /proc/softirqs

1.4 硬中断与软中断关联关系

  • 硬中断触发 → CPU 执行对应 ISR(Interrupt Service Routine)

  • ISR 中处理时间过长或处理复杂任务 → 延迟到软中断

  • 软中断(ksoftirqd)在 CPU 空闲或按调度分发执行

  • 网络收包流程示意:

NIC 收包 → 硬中断触发 ISR → 数据复制到内核缓冲 → 软中断处理协议栈 → 用户态应用

1.5 硬中断与软中断区别

项目硬中断软中断
触发方式 硬件直接触发 硬中断后内核延迟处理
执行上下文 CPU 当前上下文 ksoftirqd 内核线程
优先级
作用 立即响应设备 延迟处理任务,如网络收包
调整方法 IRQ 绑核 /proc/irq/*/smp_affinity_list RPS/RFS /sys/class/net/*/queues/rx-*

2️⃣ 网络优化基础

2.1 网卡 Offload

  • 作用:减轻 CPU 负载,让网卡处理部分网络协议

  • 常用参数

    • TSO: TCP 分段

    • GSO: 通用分段

    • GRO: 通用接收聚合

  • 查看默认状态

ethtool -k eth0
  • 开启

ethtool -K eth0 tso on gso on gro on

2.2 IRQ 绑核

  • 作用:将硬中断绑定到指定 CPU,提高多核性能

  • 设置

echo 2-15 > /proc/irq/<IRQ>/smp_affinity_list

2.3 RPS / RFS(软中断分发)

  • 作用:将软中断分发到多核,提高网络吞吐量

  • 配置文件

    • rps_cpus: CPU 掩码

    • rps_flow_cnt: RFS flow 数量

  • 查看默认值

cat /sys/class/net/eth0/queues/rx-*/rps_cpus
cat /sys/class/net/eth0/queues/rx-*/rps_flow_cnt

2.4 TCP/UDP Buffer

  • 作用:增大内核缓冲区,提升高并发性能

  • 参数

    • net.core.rmem_max

    • net.core.wmem_max

    • net.ipv4.tcp_rmem

    • net.ipv4.tcp_wmem


3️⃣ 网络优化脚本(查询/设置/打印状态)

#!/bin/bash

NIC="eth0"
CPULIST="2-15"
RMEM_MAX=16777216
WMEM_MAX=16777216
TCP_RMEM="4096 87380 16777216"
TCP_WMEM="4096 87380 16777216"
RPS_CPUS="ffff"
RPS_FLOW_ENTRIES=32768

echo "=== 网络优化: $NIC ==="

# 1️⃣ 查询默认值
echo "[1] 查询默认值"
echo "[查询] Offload:"
ethtool -k $NIC | grep -E 'tcp-segmentation|generic-segmentation|generic-receive'

echo "[查询] IRQ:"
for irq in $(grep "$NIC" /proc/interrupts | awk -F: '{print $1}' | tr -d ' '); do
    echo "$irq: $(cat /proc/irq/$irq/smp_affinity_list)"
done

echo "[查询] TCP/UDP buffer:"
sysctl net.core.rmem_max net.core.wmem_max net.ipv4.tcp_rmem net.ipv4.tcp_wmem

echo "[查询] RPS/RFS:"
for q in /sys/class/net/$NIC/queues/rx-*; do
    echo "$q: RPS=$(cat $q/rps_cpus) FLOW=$(cat $q/rps_flow_cnt)"
done

# 2️⃣ 设置优化参数
echo "[2] 设置优化参数"

echo "[设置] Offload"
ethtool -K $NIC tso on gso on gro on

echo "[设置] IRQ 绑核"
for irq in $(grep "$NIC" /proc/interrupts | awk -F: '{print $1}' | tr -d ' '); do
    echo $CPULIST > /proc/irq/$irq/smp_affinity_list
done

echo "[设置] TCP/UDP buffer"
sysctl -w net.core.rmem_max=$RMEM_MAX
sysctl -w net.core.wmem_max=$WMEM_MAX
sysctl -w net.ipv4.tcp_rmem="$TCP_RMEM"
sysctl -w net.ipv4.tcp_wmem="$TCP_WMEM"

echo "[设置] RPS/RFS"
for q in /sys/class/net/$NIC/queues/rx-*; do
    echo $RPS_CPUS > $q/rps_cpus
    echo $RPS_FLOW_ENTRIES > $q/rps_flow_cnt
done

# 3️⃣ 打印设置后状态
echo "[3] 设置完成后的状态"
ethtool -k $NIC | grep -E 'tcp-segmentation|generic-segmentation|generic-receive'
for irq in $(grep "$NIC" /proc/interrupts | awk -F: '{print $1}' | tr -d ' '); do
    echo "$irq: $(cat /proc/irq/$irq/smp_affinity_list)"
done
sysctl net.core.rmem_max net.core.wmem_max net.ipv4.tcp_rmem net.ipv4.tcp_wmem
for q in /sys/class/net/$NIC/queues/rx-*; do
    echo "$q: RPS=$(cat $q/rps_cpus) FLOW=$(cat $q/rps_flow_cnt)"
done
echo "=== 优化完成 ==="

4️⃣ 完全动态软中断统计脚本

#!/bin/bash
awk '
BEGIN {
    delete softirq_counts
    delete softirq_names
    num_types = 0
}
{
    if (NR == 1) { ncpus = NF - 1; next }
    current_type = $1; gsub(/:/, "", current_type)
    if (!(current_type in softirq_counts)) { num_types++; softirq_names[num_types] = current_type }
    for (i=2; i<=NF; i++) { softirq_counts[current_type] += $i }
}
END {
    total = 0
    for (type in softirq_counts) { total += softirq_counts[type] }
    if (total == 0) {
        print "错误: 未读取到任何软中断数据"
        exit 1
    }

    printf "%-12s %15s %10s\n", "中断类型", "总计", "占比"
    printf "==========================================\n"
    PROCINFO["sorted_in"] = "@val_num_desc"
    for (type in softirq_counts) {
        ratio = (softirq_counts[type] / total) * 100
        printf "%-12s %15d %9.2f%%\n", type, softirq_counts[type], ratio
    }
    printf "==========================================\n"
    printf "%-12s %15d %10s\n", "总计", total, "100.00%"
}
' /proc/softirqs

5️⃣ 完全动态硬中断统计脚本

#!/bin/bash
awk '
BEGIN {
    printf "%-20s %-30s %12s %10s\n", "控制器类型", "设备/描述", "中断计数", "占比(%)"
    print "----------------------------------------------------------------"
}
NR == 1 { ncpus = NF - 1; next }
/^[ \t]*$/ { next }
/:/ && $1 ~ /^[0-9]+:/ {
    irq_num = substr($1, 1, length($1)-1)
    sum = 0
    for (i=2; i<=1+ncpus; i++) { sum += $i }
    if (sum == 0) next
    controller = $(NF-1)
    device = $NF
    total_irqs += sum
    key = controller "|" device
    counts[key] += sum
    ctrl_totals[controller] += sum
}
END {
    if (total_irqs == 0) { print "未读取到有效中断数据"; exit 1 }
    PROCINFO["sorted_in"] = "@val_num_desc"
    for (key in counts) {
        split(key, parts, "|")
        ratio = (counts[key]*100.0)/total_irqs
        printf "%-20s %-30s %12d %9.2f%%\n", parts[1], parts[2], counts[key], ratio
    }
    print "==============================================="
    for (ctrl in ctrl_totals) {
        ratio = (ctrl_totals[ctrl]*100.0)/total_irqs
        printf "%-20s %12d %9.2f%%\n", ctrl, ctrl_totals[ctrl], ratio
    }
    printf "%-20s %12d %10s\n", "总中断数", total_irqs, "100.00%"
}
' /proc/interrupts

6️⃣ 使用说明

  • 网络优化:执行 ./network_optimize.sh 查询、设置和打印网卡优化状态

  • 软中断统计:执行 ./softirq_stats.sh 显示各类型软中断总数和占比

  • 硬中断统计:执行 ./hardirq_stats.sh 显示硬中断详细分类及占比

  • 诊断优化:根据输出占比高的中断类型,可调整 RPS/RFS、IRQ 绑核或硬件升级


7️⃣ 性能分析(Perf 全套流程)

7.1 Step1: 基础统计

perf stat -a -d sleep 5
指标、现象、分析工具、方法及可能原因
指标现象描述分析工具分析方法可能原因
cycles CPU 总周期 perf stat 与 instructions 对比计算 CPI CPU 负载高,频率低或节能模式
instructions 执行指令数 perf stat CPI = cycles / instructions CPU pipeline stall
cache-references 缓存访问次数 perf stat 比较 cache-miss 高 miss → CPU stall 或 NUMA 远程访问
cache-misses 缓存未命中次数 perf stat cache miss rate CPU stall / NUMA 远程访问
branch-instructions 分支指令数 perf stat branch-misses rate 分支预测失误 → pipeline stall
branch-misses 分支错误次数 perf stat 分支预测失误分析 高 → pipeline stall
context-switches 上下文切换次数 perf stat / perf sched 高但 syscall 正常 → 调度/锁瓶颈 锁争用、调度延迟
cpu-migrations 进程迁移次数 perf stat perf sched / top NUMA、负载均衡影响
page-faults 页面错误次数 perf stat / vmstat 高 → 内存不足或 NUMA 远程访问 内存压力、NUMA 远程访问
minor-faults 非阻塞页错误 perf stat / vmstat 频繁 → 内存压力 内存不足
major-faults 阻塞页错误 perf stat / iostat 频繁 → I/O 或内存压力 磁盘/网络 I/O 瓶颈
cycles.stalled CPU 停顿周期 perf stat cycles stalled analysis pipeline stall / cache miss
instructions.retired 指令完成数 perf stat CPI / IPC 分析 CPU pipeline / IPC 效率
syscalls 系统调用次数 perf trace 高频 syscall 追踪 I/O / 网络 / 文件系统瓶颈

分析流程

  1. CPU:CPI 高、cache-miss 高 → CPU stall 或 pipeline 问题

  2. 内存:page-fault 高 → 内存不足或 NUMA 远程访问

  3. 调度:context-switch 高,但 syscall 正常 → 调度/锁争用

  4. I/O:syscalls 高、major page faults 高 → I/O 瓶颈

  5. 系统调用:特定 syscall 高频 → 分析网络/文件/磁盘瓶颈


7.2 Step2: 系统调用跟踪

perf trace -a
  • 找出最耗时系统调用

  • 分析 I/O、网络、文件操作瓶颈


7.3 Step3: 调度/锁分析

perf sched record -a -g sleep 10
perf sched latency
  • 查看 ksoftirqd、kworker 调度延迟

  • 分析 context-switch 高原因


7.4 Step4: 热点分析

perf top -a
  • 实时查看 CPU 消耗最高函数

  • 检查是否卡在:

    • schedule() / io_schedule()

    • 内核网络或 I/O 函数

    • 用户态 CPU 密集函数


7.5 Step5: 深入分析

perf record -a -g sleep 10
perf report
  • 获取调用栈

  • 分析热点函数

  • 判断 NUMA 远程访问、宿主机 I/O 调度延迟


7.6 Step6: 分支思路总结

现象分析方法可能原因
syscalls 高 perf trace -a I/O/网络/文件系统瓶颈
context-switch 高 perf sched record/latency 调度/锁争用
page-fault 高 /proc/softirqs + perf top 内存/NUMA 远程访问
CPI 高但 syscall/ctx/fault 正常 perf top -a CPU stall、cache miss、NUMA

8️⃣ 网络优化 + 性能诊断闭环流程图

+---------------------+
|     网络收包         |
|  (NIC Hard IRQ)     |
+---------+-----------+
          |
          v
+---------------------+
|  硬中断绑核 / RPS    |
|  irq_affinity / RPS  |
+---------+-----------+
          |
          v
+---------------------+
|   ksoftirqd / SoftIRQ |
|   (网络、调度任务)   |
+---------+-----------+
          |
          v
+---------------------+
|      TCP/UDP Buffer  |
|  rmem/wmem/tcp_*    |
+---------+-----------+
          |
          v
+---------------------+
| 用户态应用 / syscall |
| perf stat/top 分析  |
+---------+-----------+
          |
          v
+---------------------+
| 调度 / 锁分析       |
| perf sched/latency  |
+---------+-----------+
          |
          v
+---------------------+
| 深入热点分析         |
| perf record/report   |
+---------------------+

✅ 此文档 完整保留了原有内容,并对基础统计、指标分析、现象、分析工具、方法和可能原因做了详细扩展,硬/软中断触发机制及关联关系也已完善,可直接作为性能诊断闭环操作手册。


 

posted on 2025-09-22 13:06  吃草的青蛙  阅读(10)  评论(0)    收藏  举报

导航