Skip to content

终端性能监控深度解析

100 天认知提升计划 | Day 3


目录


第一部分:监控工具全景

常见工具对比

系统资源监控工具矩阵

工具语言特点适用场景资源占用
btopC++美观、主题丰富、交互流畅日常监控首选
zenithRustGPU 支持、SQLite 历史存储长期趋势分析
htopC经典、轻量、高度可定制服务器环境极低
btmRust跨平台、进程树可视化开发者调试
nvitopPythonNVIDIA GPU 专用AI/ML 工作负载
bandwhichRust进程级网络带宽分解网络问题排查
procsRust彩色输出、Docker 支持进程管理极低
glancesPythonWeb UI、API、告警远程监控

工具选择决策树

需要监控什么?
├── CPU/内存/磁盘/网络基础监控
│   ├── 追求美观交互 → btop
│   ├── 服务器极简 → htop
│   └── 需要历史数据 → zenith
├── GPU 监控
│   ├── NVIDIA → nvitop
│   └── 通用 → zenith
├── 网络问题排查
│   └── 进程级带宽 → bandwhich
└── 远程/集群监控
    └── glances (Web UI)

底层实现原理

数据采集架构

┌─────────────────────────────────────────────────────────────┐
│                     监控工具 (btop/htop)                      │
│                         用户态                                │
├─────────────────────────────────────────────────────────────┤
│                          │                                   │
│     ┌────────────────────┼────────────────────┐              │
│     │                    │                    │              │
│     ▼                    ▼                    ▼              │
│  ┌────────┐         ┌────────┐          ┌──────────┐         │
│  │/proc   │         │/sys    │          │系统调用   │         │
│  │文件系统 │         │文件系统 │          │(syscalls)│         │
│  │        │         │        │          │          │         │
│  │/proc/  │         │/sys/   │          │sysctl    │         │
│  │  [pid]/│         │  class/│          │getrusage │         │
│  │  stat  │         │  net/  │          │sysinfo   │         │
│  │  status│         │  fs/   │          │times     │         │
│  │  fd/   │         │  block/│          │          │         │
│  └────┬───┘         └───┬────┘          └────┬─────┘         │
│       │                 │                    │               │
└───────┼─────────────────┼────────────────────┼───────────────┘
        │                 │                    │
        ▼                 ▼                    ▼
   ┌──────────────────────────────────────────────────────┐
   │                    Linux 内核                         │
   │  ┌──────────┐  ┌──────────┐  ┌──────────┐            │
   │  │ 调度器    │  │ 内存管理  │  │ 网络栈    │            │
   │  │ (CFS)    │  │ (SLUB)   │  │ (TCP/IP) │            │
   │  └──────────┘  └──────────┘  └──────────┘            │
   └──────────────────────────────────────────────────────┘

核心数据源详解

  1. /proc 文件系统(进程信息)
bash
# 进程状态信息
cat /proc/$$/stat
# 输出: 1234 (bash) S 1233 ...
# 字段: pid (comm) state ppid ... utime stime ... rss

# 详细进程信息
cat /proc/$$/status
# Name:   bash
# State:  S (sleeping)
# Tgid:   1234
# Pid:    1234
# PPid:   1233
# VmRSS:  12340 kB  # 实际物理内存
# VmSize: 45678 kB  # 虚拟内存
# Threads: 1
# voluntary_ctxt_switches: 1234    # 主动上下文切换
# nonvoluntary_ctxt_switches: 56   # 被动上下文切换

# 进程打开的文件
cat /proc/$$/fd/0  # stdin
ls -la /proc/$$/fd/  # 所有文件描述符

# 进程的 CPU 时间统计
cat /proc/$$/stat | awk '{print "UTIME: " $14, "STIME: " $15}'
  1. /sys 文件系统(系统信息)
bash
# CPU 信息
cat /sys/class/thermal/thermal_zone0/temp  # CPU 温度 (毫摄氏度)
# 输出: 45000 (表示 45°C)

cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq  # 当前频率
# 输出: 2400000 (表示 2.4GHz)

# 内存信息
cat /sys/fs/cgroup/memory/memory.usage_in_bytes  # cgroup 内存使用
cat /sys/fs/cgroup/memory/memory.limit_in_bytes  # cgroup 内存限制

# 磁盘 I/O
cat /sys/block/sda/stat
# 输出: 读完成数 读扇区数 写完成数 写扇区数 ...

# 网络接口统计
cat /sys/class/net/eth0/statistics/rx_bytes  # 接收字节数
cat /sys/class/net/eth0/statistics/tx_bytes  # 发送字节数
cat /sys/class/net/eth0/statistics/rx_packets  # 接收包数
cat /sys/class/net/eth0/statistics/rx_errors   # 接收错误数
  1. 系统调用接口
c
// 获取系统级统计信息
#include <sys/sysinfo.h>
struct sysinfo info;
sysinfo(&info);
// info.uptime     - 系统运行时间
// info.totalram   - 总内存
// info.freeram    - 空闲内存
// info.procs      - 进程数

// 获取资源使用
#include <sys/resource.h>
struct rusage usage;
getrusage(RUSAGE_SELF, &usage);
// usage.ru_utime  - 用户态 CPU 时间
// usage.ru_stime  - 内核态 CPU 时间
// usage.ru_maxrss - 最大常驻内存
// usage.ru_minflt - 软缺页次数
// usage.ru_majflt - 硬缺页次数
// usage.ru_nvcsw  - 自愿上下文切换
// usage.ru_nivcsw - 非自愿上下文切换

第二部分:性能影响分析

监控工具的开销来源

开销构成分析

监控工具总开销 = 数据采集开销 + 数据处理开销 + 渲染开销 + 更新频率开销

1. 数据采集开销 (通常最小)
   - /proc 读取: ~0.01-0.1ms/次
   - /sys 读取: ~0.01-0.1ms/次
   - 系统调用: ~0.1-1ms/次

2. 数据处理开销 (中等)
   - 解析文本数据
   - 计算增量值 (如 CPU 使用率)
   - 排序和过滤进程

3. 渲染开销 (最大)
   - 终端输出 (特别是彩色、Unicode)
   - 图形绘制 (如 btop 的进度条)
   - 屏幕刷新

4. 更新频率开销
   - 100ms 间隔: ~1-5% CPU
   - 1000ms 间隔: ~0.1-0.5% CPU

不同工具的开销对比

工具典型 CPU 占用内存占用主要开销来源
htop0.5-2%2-5 MB进程列表渲染
btop1-3%5-10 MB图形渲染、主题处理
zenith1-4%10-20 MBSQLite 写入、历史存储
nvitop2-5%20-50 MBPython 运行时、NVML 调用
glances2-8%30-80 MBPython 运行时、Web 服务

底层开销细节

bash
# 测量 htop 的资源消耗
# 终端 1: 运行被监控程序
yes > /dev/null &
PID=$!

# 终端 2: 监控 htop 本身的消耗
ps -p $(pgrep htop) -o pid,ppid,%cpu,%mem,time,comm

# 查看 htop 的系统调用统计
strace -c -p $(pgrep htop) 2>&1 | head -20
# 典型输出:
# % time     seconds  usecs/call     calls    errors syscall
# ------ ----------- ----------- --------- --------- ----------------
#  45.23    0.023456          23      1024           read
#  23.12    0.012345          45       275           write
#  15.67    0.008234          12       689           openat
#  ...

# 查看 btop 的打开文件(频繁读取 /proc)
lsof -p $(pgrep btop) | grep /proc | wc -l
# 输出: 200+ (取决于进程数)

降低监控开销的方法

配置优化建议

bash
# 1. 降低更新频率
# btop 配置 (~/.config/btop/btop.conf)
update_ms = 2000  # 改为 2 秒而不是默认 100ms

# htop 配置 (F2 → Display options → Delay)
# 设置为 5.0 (500ms) 或更高

# 2. 减少显示内容
# btop: 禁用不需要的板块
show_disks = false
show_network = false
show_battery = false

# 3. 使用轻量级替代
top     # 极简模式
watch -n 5 'ps aux --sort=-%cpu | head'  # 简单脚本替代

生产环境监控策略

开发/测试环境          生产环境(需要时)       长期监控
    │                      │                   │
    ▼                      ▼                   ▼
┌─────────┐           ┌─────────┐         ┌─────────┐
│ btop    │           │ htop    │         │ sar     │
│ zenith  │           │ pidstat │         │ vmstat  │
│ 实时    │           │ 按需启动 │         │ 后台收集 │
└─────────┘           └─────────┘         └─────────┘
   高交互                低开销               无侵入

第三部分:可见与不可见的指标

用户态可见指标

标准监控工具能看到的指标

类别可见指标数据来源更新频率
CPU使用率%、用户态/内核态比例/proc/stat实时
进程 CPU 占用排行/proc/[pid]/stat实时
负载平均值 (1/5/15min)/proc/loadavg实时
CPU 频率、温度/sys/class/按需
内存总量/已用/空闲/缓存/proc/meminfo实时
进程 RSS/VIRT 内存/proc/[pid]/status实时
Swap 使用情况/proc/swaps实时
磁盘读写速率、IOPS/proc/diskstats实时
磁盘使用百分比statfs 系统调用按需
网络收发字节/包数/sys/class/net/实时
连接状态统计/proc/net/tcp实时
进程PID、命令、用户、优先级/proc/[pid]/实时
线程数、文件描述符数/proc/[pid]/status实时

示例:从 /proc 读取各项指标

bash
# CPU 统计(从系统启动开始的累计值)
cat /proc/stat | head -5
# cpu  123456 2345 34567 4567890 5678 890 123 4567 0 0 0
#      用户态  nice 内核态  空闲    io等待 硬中断 软中断 偷取
# 计算使用率: 1 - (空闲差值/总差值)

# 内存统计
cat /proc/meminfo | head -10
# MemTotal:       16384000 kB
# MemFree:         2345678 kB
# MemAvailable:    5678901 kB  # 实际可用(包含缓存)
# Buffers:          123456 kB
# Cached:          3456789 kB
# SwapCached:            0 kB
# Active:          4567890 kB
# Inactive:        2345678 kB

# 进程统计示例
PID=1  # init 进程
cat /proc/$PID/stat | tr ' ' '\n' | nl
#  1  1           # PID
#  2  (systemd)   # 命令名
#  3  S           # 状态 (S=sleeping, R=running, Z=zombie)
#  14 123456      # 用户态 CPU 时间 (clock ticks)
#  15 23456       # 内核态 CPU 时间
#  24 5678        # 内存页数 (RSS)

内核态隐藏指标

监控工具通常看不到的指标

隐藏指标为什么看不到如何查看
CPU 微架构事件需要 rdmsr/perfperf stat
Cache Miss 率需要硬件 PMUperf stat -e cache-misses
分支预测失败需要硬件 PMUperf stat -e branch-misses
内核调度延迟需要 tracepointbpftraceftrace
软中断分布需要 /proc/softirqs 解析watch -n1 cat /proc/softirqs
页面回收活动需要 vmstat 详细模式vmstat -s
TCP 内部状态需要 ss -tinss -tin

深入查看隐藏指标

bash
# 1. 使用 perf 查看硬件级事件
perf stat -a sleep 5
# 输出示例:
#  5,123.45 msec cpu-clock                 # CPU 时间
#  12,345,678      cycles                  # CPU 周期
#  23,456,789      instructions            # 指令数
#  0.53            insn per cycle          # IPC (越高越好)
#  345,678         cache-references        # 缓存访问
#  45,678          cache-misses            # 缓存未命中 (13.2%)

# 2. 查看调度延迟 (需要 root)
bpftrace -e 'kprobe:schedule { @start[tid] = nsecs; } 
             kprobe:finish_task_switch /@start[tid]/ 
             { @latency = hist((nsecs - @start[tid])/1000); 
               delete(@start[tid]); }'

# 3. 软中断统计
cat /proc/softirqs
#           CPU0       CPU1       CPU2       CPU3
# HI:          0          0          0          0
# TIMER:   12345      23456      34567      45678
# NET_TX:    123        234        345        456
# NET_RX:   5678       6789       7890       8901
# BLOCK:    1234       2345       3456       4567
# BLOCK_IOPOLL: 0          0          0          0
# TASKLET:     0          0          0          0
# SCHED:    3456       4567       5678       6789
# HRTIMER:   123        234        345        456
# RCU:      5678       6789       7890       8901

# 4. 内核级内存统计
vmstat -s
#     16384000 K total memory
#      2345678 K used memory
#      ...
#        12345 K pages paged in        # 页面换入
#        23456 K pages paged out       # 页面换出
#          789 K pages swapped in      # swap 换入
#          123 K pages swapped out     # swap 换出
#     12345678 interrupts              # 中断总数
#     23456789 CPU context switches    # 上下文切换

硬件级指标

需要特殊工具才能查看

指标工具用途
CPU 温度/功耗sensors (lm-sensors)热管理
内存频率/时序dmidecode硬件诊断
磁盘 SMARTsmartctl磁盘健康
GPU 利用率nvidia-smi/nvitopAI/图形负载
网络丢包率ethtool -S网卡诊断
电源状态powertop能耗分析

第四部分:btop 实战详解

界面布局与指标解读

btop 标准界面布局

┌──────────────────────────────────────────────────────────────┐
│  1. 标题栏 (系统信息)                                         │
│  2. CPU 区域 (核心使用率 + 整体图表)                          │
│  3. 内存区域 (RAM + Swap 使用)                                │
│  4. 网络区域 (收发速率 + 累计流量)                            │
│  5. 磁盘区域 (各分区使用率 + IO)                              │
│  6. 进程区域 (列表 + 详细信息)                                │
└──────────────────────────────────────────────────────────────┘

1. CPU 区域详解

CPU  Usage:  25% █████░░░░░░░░░░░░░░░  
             用户态 ▲        内核态 ▼

Core 0:  45% █████████░░░░░░░░░░░  [▲频率: 3.2GHz]
Core 1:  12% ██░░░░░░░░░░░░░░░░░░  [ 频率: 1.2GHz]
Core 2:  78% ████████████████░░░░  [▲频率: 4.5GHz]  ← 高频表示负载高
...

┌─────────────────────────────────────────────────────┐
│ CPU 使用率历史图 (最近 60 秒)                        │
│ ▁▃▅▇██▇▅▃▁▁▂▄▆▇███▇▆▄▂▁▁▃▅▇█▇▅▃▁▁▂▄▆▇█▇▆▄▂▁▁▃▅▇▇│
└─────────────────────────────────────────────────────┘

各值含义:
- 使用率%: (1 - 空闲时间/总时间) × 100
- 频率: /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq
- 历史图: 每秒采样的使用率连线

2. 内存区域详解

Memory: 8.45G / 16.00G [████████████░░░░░░░░] 53%
Swap:   0.00G / 4.00G  [░░░░░░░░░░░░░░░░░░░░] 0%

详细解读:
- 8.45G: 实际使用 (RSS 类总和,不含缓存)
- 16.00G: 总物理内存
- 53%: 使用率
- Swap 使用率低 = 系统内存充足

内存使用组成 (按 /proc/meminfo):
- 应用程序: 实际分配并使用的内存
- 缓存/缓冲: 文件系统缓存 (可回收)
- 内核占用: 内核数据结构、驱动

3. 网络区域详解

Net: ▲ 1.5 MB/s  ▼ 45 KB/s
     ↑上传       ↓下载

详细统计:
Total: ▲ 12.5 GB  ▼ 89.3 GB
       总上传量    总下载量

Interface: en0 (Wi-Fi)
SSID: MyNetwork
Signal: ████████░░ 80%

网络连接状态 (按协议):
TCP:  45 连接 (ESTABLISHED: 12, TIME_WAIT: 30)
UDP:  8  监听

4. 进程区域详解

┌────────────────────────────────────────────────────────────┐
│ PID    USER     PRI  NI  VIRT   RES   CPU%  MEM%  TIME+   CMD │
│ 1234   user      20   0  1.2G   456M  45.2  2.8   1:23.45 node │
│ 5678   root      20   0  2.5G   890M  12.3  5.5   2:34.56 java │
│ ...                                                         │
└────────────────────────────────────────────────────────────┘

各列含义:
- PID:    进程 ID
- USER:   运行用户
- PRI:    优先级 (越小越优先,0-139)
- NI:     Nice 值 (-20 到 19,负值更高优先级)
- VIRT:   虚拟内存 (代码+数据+共享库+swap)
- RES:    常驻内存 (实际物理内存)
- CPU%:   CPU 使用率 (采样间隔内)
- MEM%:   内存使用率 (RES/总内存)
- TIME+:  累计 CPU 时间
- CMD:    命令名

配置与自定义

btop 配置文件位置

bash
# 主配置文件
~/.config/btop/btop.conf

# 主题文件目录
~/.config/btop/themes/

# 常用主题
# - default
# - dracula
# - gruvbox
# - nord
# - solarized_dark

推荐配置

bash
# ~/.config/btop/btop.conf

# 更新频率 (毫秒)
update_ms = 1000

# 配色方案
color_theme = "dracula"

# 显示设置
show_cpu = true
show_mem = true
show_net = true
show_disks = true
show_battery = false  # 台式机关闭

# CPU 设置
cpu_graph_upper = "total"  # total/user/system
cpu_graph_lower = "idle"
cpu_single_graph = false   # 显示所有核心

# 进程设置
proc_sorting = "cpu"       # cpu/mem/pid/user/...
proc_reversed = false
proc_tree = false          # 树形显示
proc_colors = true

# 网络设置
net_sync = false           # 同步收发刻度
net_auto = true            # 自动选择主网卡

# 磁盘设置
disk_free_priv = true      # 显示特权信息

键盘快捷键

按键功能
h显示帮助
q / Esc退出
Tab切换进程排序
Shift+Tab反向切换排序
f进程筛选
k / d杀死进程
s切换信号 (9/KILL, 15/TERM)
e切换进程树视图
m切换内存单位 (MB/GB/auto)
1-4切换帮助页面
+ / -调整更新频率

问题排查实战

场景 1:CPU 使用率异常高

观察到的现象:
CPU Usage:  95% ███████████████████░
Core 0:  98% ████████████████████
Core 1:  92% ███████████████████░
...

排查步骤:
1. 按 CPU% 排序 (默认)
2. 找到 CPU 占用最高的进程
3. 查看进程详情:
   - 选中进程 → 查看 COMMAND 列完整命令
   - 确认是否为预期中的进程

4. 进一步诊断:
   # 查看该进程的系统调用
   strace -p <PID> -c
   
   # 查看线程级 CPU 使用
   ps -eLf | grep <PID>
   
   # 查看进程打开的文件
   lsof -p <PID>

5. 常见原因:
   - 死循环/ busy waiting
   - 频繁的 I/O 操作
   - 内存不足导致的频繁 GC
   - 不合理的并发

场景 2:内存持续增长

观察到的现象:
Memory: 15.2G / 16.0G [███████████████████░] 95%
Swap:   2.1G / 4.0G   [████████░░░░░░░░░░░░] 53%

排查步骤:
1. 按 MEM% 排序 (Tab 切换到 memory)
2. 识别内存占用最高的进程
3. 分析内存类型:
   - VIRT 高但 RES 低 → 内存映射文件,正常
   - RES 持续增长 → 内存泄漏嫌疑
   
4. 进一步诊断:
   # 查看进程内存映射
   pmap -x <PID> | sort -k3 -n | tail -20
   
   # 查看进程的详细内存统计
   cat /proc/<PID>/status | grep -E "Vm|Rss"
   
   # 查看堆内存分配 (如果是 Java/Go)
   # Java: jmap -heap <PID>
   # Go:   GODEBUG=gctrace=1 ./program

5. 常见原因:
   - 内存泄漏 (未释放的对象)
   - 缓存未设置上限
   - 大文件加载到内存
   - 内存碎片

场景 3:磁盘 IO 瓶颈

观察到的现象:
Disk: /dev/sda
  IO%: 98% ████████████████████
  Read:  120 MB/s
  Write: 5 MB/s

排查步骤:
1. 切换到磁盘视图 (如果配置显示)
2. 查看具体哪个分区 IO 高
3. 找出 IO 密集的进程:
   # 使用 iotop 查看
   sudo iotop -o
   
   # 或使用 pidstat
   pidstat -d 1

4. 分析 IO 模式:
   # 查看进程的 IO 统计
   cat /proc/<PID>/io
   # rchar: 读取字节数
   # wchar: 写入字节数
   # syscr: 读系统调用次数
   # syscw: 写系统调用次数

5. 优化建议:
   - 增加缓存
   - 使用更快的存储 (SSD)
   - 优化访问模式 (顺序 vs 随机)
   - 调整文件系统参数

场景 4:网络连接过多

观察到的现象:
TCP:  4500 连接 (ESTABLISHED: 1200, TIME_WAIT: 3200)

排查步骤:
1. 查看连接状态分布:
   ss -tan | awk '{print $1}' | sort | uniq -c
   
2. 如果是 TIME_WAIT 过多:
   # 查看具体的 TIME_WAIT 连接
   ss -tan state time-wait | wc -l
   
   # 可能原因:
   # - 短连接过多
   # - 连接池配置不当
   # - TIME_WAIT 超时时间过长

3. 找出高频连接的进程:
   ss -tanp | awk '{print $7}' | sort | uniq -c | sort -rn

4. 优化建议:
   # 调整 TCP 参数 (临时)
   sudo sysctl -w net.ipv4.tcp_tw_reuse=1
   sudo sysctl -w net.ipv4.tcp_fin_timeout=15
   
   # 使用连接池
   # 增加 keep-alive

第五部分:实践与思考

实践记录

工具安装清单

bash
# macOS
brew install btop zenith procs bandwhich
pip install nvitop

# Linux (Ubuntu/Debian)
sudo apt install btop
# 或从源码编译最新版
git clone https://github.com/aristocratos/btop.git
cd btop && make && sudo make install

# 其他工具
cargo install zenith bandwhich procs

btop 配置实践

  • [ ] 安装 btop 并选择喜欢的主题
  • [ ] 配置更新频率为 1 秒 (生产环境建议)
  • [ ] 配置只显示必要的板块 (减少开销)
  • [ ] 创建启动别名: alias mon='btop --update 2000'

性能监控脚本

bash
#!/bin/bash
# ~/bin/resource-alert

# CPU 告警阈值
CPU_THRESHOLD=80
# 内存告警阈值  
MEM_THRESHOLD=90

while true; do
    CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)
    MEM_USAGE=$(free | grep Mem | awk '{printf "%.0f", $3/$2 * 100.0}')
    
    if (( $(echo "$CPU_USAGE > $CPU_THRESHOLD" | bc -l) )); then
        osascript -e 'display notification "CPU 使用率超过 80%" with title "系统告警"'
    fi
    
    if [ "$MEM_USAGE" -gt "$MEM_THRESHOLD" ]; then
        osascript -e 'display notification "内存使用率超过 90%" with title "系统告警"'
    fi
    
    sleep 60
done

各指标正常范围参考

指标健康范围警告范围危险范围
CPU 使用率< 70%70-85%> 85%
内存使用率< 70%70-85%> 85%
Swap 使用率0%< 20%> 50%
磁盘 IO%< 60%60-80%> 80%
负载平均值< CPU 核心数1-2x 核心数> 2x 核心数
网络重传率< 1%1-5%> 5%

疑问与思考

已解答

  1. ✅ 终端监控工具的数据从哪里来?

    • 主要来自 /proc/sys 伪文件系统
    • 还有系统调用如 sysinfo()getrusage()
  2. ✅ 为什么 btop 比 htop 占用更多资源?

    • btop 使用更复杂的图形渲染
    • 支持更多自定义主题和动画效果
    • 默认更新频率更快
  3. ✅ 哪些指标是标准工具看不到的?

    • 硬件级事件 (cache miss、branch prediction)
    • 内核调度延迟
    • 详细的内存分配统计
  4. ✅ 如何在生产环境低侵入地监控系统?

    • 使用 sarvmstat 等后台收集工具
    • 监控工具按需启动,不常驻
    • 增加采样间隔到 5-10 秒

待探索

  1. ❓ 如何自定义 btop 主题?
  2. ❓ eBPF 能否提供更精细的监控数据?
  3. ❓ 如何将 btop 数据导出到 Prometheus?
  4. ❓ 容器环境下的监控有何不同?

更新日期:2026-02-12

用 ❤️ 和 AI 辅助学习