CPU使用率不高但系统卡顿通常因I/O等待或内存压力;需用iostat、vmstat、pidstat定位瓶颈,MemAvailable和PageTables比MemFree更能反映真实内存状况。

为什么 top 显示 CPU 使用率不高,但系统明显卡顿?
这通常不是 CPU 瓶颈,而是 I/O 等待(%wa)或内存压力导致的。Linux 的 CPU 使用率只统计非等待态时间,当进程大量阻塞在磁盘读写或锁竞争时,top 里的 %us/%sy 会偏低,但实际响应迟缓。
- 先运行
iostat -x 1查看%util和await:若%util > 80%且await持续高于 10ms,说明磁盘已饱和 - 用
vmstat 1观察si/so(swap in/out):非零值意味着内存不足,内核频繁换页 -
pidstat -d 1可定位具体哪个进程在发起大量 I/O
如何判断是内存不足还是内存泄漏?
关键看 /proc/meminfo 中的 MemAvailable 和 PageTables,而不是简单对比 MemTotal 与 MemFree。Linux 会积极使用空闲内存做 cache,MemFree 小不等于内存紧张。
- 真正可用内存看
MemAvailable:低于总内存 5% 时需警惕 - 检查
PageTables是否异常增长(>1GB):可能有进程创建了海量小对象或 mmap 区域,未释放 - 用
cat /sys/fs/cgroup/memory/memory.usage_in_bytes(如启用 cgroup v1)查看容器/服务实际内存占用 - 对疑似泄漏进程,用
pstack+cat /proc/结合分析堆栈和内存映射分布/maps
sysctl.conf 里哪些参数改了反而有害?
盲目调大 vm.swappiness 或调小 vm.vfs_cache_pressure 是常见误区。这些参数作用机制复杂,脱离 workload 盲调极易引发副作用。
-
vm.swappiness=0并不禁止 swap,只是延迟触发;若物理内存耗尽,仍会 OOM kill 进程 —— 不如设为1更稳妥 vm.vfs_cache_pressure 会让 dentry/inode cache 过度驻留,挤占 page cache,反而降低文件读取性能-
net.ipv4.tcp_tw_reuse=1在负载均衡后端或 NAT 环境下可能导致连接复用冲突,应优先用net.ipv4.tcp_fin_timeout缩短 TIME_WAIT 持续时间
磁盘 I/O 优化绕不开的三个真实约束
SSD 并不万能。即使换成 NVMe,若应用层仍是随机小写、无合并、无预分配,I/O 性能依然上不去。瓶颈常在软件栈,不在硬件。
- ext4 默认启用
journal=ordered,写日志会串行化元数据更新;高并发小文件写入场景可考虑data=writeback(需接受崩溃后文件系统不一致风险) - 数据库类应用务必关闭文件系统 barrier:
mount -o barrier=0(仅限电池供电 RAID 或支持断电保护的 SSD) - 避免让
rsync、logrotate等工具在高峰时段执行全盘扫描 —— 它们触发的readahead会污染 page cache,建议加--drop-cache或用ionice -c3降级 I/O 优先级
#!/bin/bash
# 快速检测当前 I/O 压力基线(无需安装额外工具)
echo "=== I/O wait & memory pressure ==="
grep 'cpu ' /proc/stat | awk '{print 100-$5/($2+$3+$4+$5+$6+$7+$8+$9+$10+$11)*100}' | xargs printf "CPU idle: %.1f%%\n"
awk '/^pgpgin|pgpgout|pswpin|pswpout/ {sum+=$2} END {print "I/O pages/sec:", sum/10}' /proc/vmstat 2>/dev/null
真正难优化的从来不是单个指标,而是多个子系统间的隐式耦合 —— 比如调整网络 buffer 大小会影响 TCP 内存分配策略,进而改变 page cache 回收行为。动手前,先用 perf record -e block:block_rq_issue,block:block_rq_complete -a sleep 30 看清 I/O 请求的真实生命周期。









