需两次采样/proc/diskstats取差值再除以时间间隔,第6、10列扇区数须乘512换算为字节,优先匹配主设备行(minor=0),间隔≥100ms以避免噪声。

Linux下用/proc/diskstats解析物理磁盘I/O吞吐量
Linux没有现成的API直接返回“实时MB/s”,得自己算。核心依据是/proc/diskstats里每行末尾的第10、11字段:读/写字节数(单位是扇区,512字节)。两次采样相减再除以时间差,就能得到真实吞吐量。
容易踩的坑:diskstats里同一设备可能有多个条目(比如sda和sda1),必须匹配主设备名(不含数字后缀);扇区数是累计值,不能直接用单次读取值;采样间隔建议≥100ms,太短会导致浮点精度失真或归零。
示例逻辑:
std::ifstream f("/proc/diskstats");
std::string line;
while (std::getline(f, line)) {
std::istringstream iss(line);
std::string major, minor, name;
iss >> major >> minor >> name;
if (name == "sda" || name == "nvme0n1") { // 过滤物理设备名
long long rd_sectors, wr_sectors;
// 跳过前9个字段,读第10(rd_sectors)、第11(wr_sectors)
for (int i = 0; i > line;
iss >> rd_sectors >> wr_sectors;
// 吞吐量 = (delta * 512) / elapsed_ms * 1000 → 字节/秒
}
}
Windows上用PDH查询PhysicalDisk% Disk Read Bytes/sec等计数器
Windows不暴露原始扇区计数,得靠性能计数器。关键路径是\PhysicalDisk(_Total)|% Disk Read Bytes/sec和\PhysicalDisk(_Total)|% Disk Write Bytes/sec——注意这里返回的是字节/秒,不是百分比(名字带%但值是绝对速率)。
常见错误:直接调PdhAddCounter传入中文本地化名称(如“物理磁盘”)会失败,必须用英文路径;_Total聚合值在多盘系统中不够准,应枚举具体实例(如0 C:对应0 C:,但底层物理盘需查Win32_DiskDrive映射);首次调用PdhCollectQueryData后必须等待至少1秒再取值,否则返回PDH_INVALID_DATA。
实操要点:
Linux 性能分析与调优专家,覆盖 CPU、内存、磁盘 I/O、网络、内核参数、编译优化、容器/K8s。适用场景:系统卡顿/高负载、内存不足/OOM/Swap 高、CPU 异常/iowait 高。
- 用
PdhOpenQuery+PdhAddCounter注册计数器时,确保字符串是UTF-16且含L"\PhysicalDisk(0 C:)\Disk Read Bytes/sec"格式 - 调用
PdhCollectQueryData后,用PdhGetFormattedCounterValue取PDH_FMT_LONG类型,避免浮点精度截断 - 不要依赖
% Disk Time,它反映的是忙时占比,不是吞吐量
C++跨平台封装时为何不能只靠statvfs或GetDiskFreeSpaceEx
statvfs和GetDiskFreeSpaceEx只返回容量/可用空间,和I/O吞吐量完全无关。试图用它们推算负载是典型误解——磁盘满不代表IO忙,空盘也可能被随机小IO打满。
真正影响吞吐量的是队列深度、寻道延迟、NVMe vs SATA协议栈开销。所以必须采集底层设备级指标(Linux的diskstats、Windows的PDH),而不是文件系统层数据。
性能提示:Linux下/proc/diskstats是纯文本读取,开销极低;Windows的PDH需初始化查询对象,首次调用耗时约1–3ms,后续PdhCollectQueryData在毫秒级。别在高频循环里重复PdhOpenQuery。
如何区分SSD/NVMe和传统HDD的实际吞吐瓶颈
单纯看字节/秒数值会误导。NVMe盘标称3GB/s,但实际业务IO往往是4K随机读写,此时IOPS比吞吐量更重要。Linux下可配合/sys/block/<device>/queue/logical_block_size</device>确认块大小,并用iostat -x 1观察%util和await——如果%util接近100但吞吐量远低于标称值,说明是IOPS瓶颈而非带宽瓶颈。
实操建议:
- 对NVMe设备,优先关注
avgqu-sz(平均队列长度)是否持续>1,这比吞吐量更能反映压力 - Windows中
PhysicalDiskAvg. Disk Queue Length同理,>2通常表示饱和 - 不要用
dd测出的顺序写速度去评估数据库负载,场景不等价
最易被忽略的一点:容器或虚拟机环境下,/proc/diskstats看到的是虚拟设备(如vdX),其吞吐量受宿主机调度限制,和物理盘无直接换算关系。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










