如何在C++应用中测量SSD读取性能与吞吐量?WSL2遇0值问题
WSL2下用io_uring测SSD性能时/proc/diskstats和perf返回0值的解决办法
问题原因
WSL2的虚拟化架构导致系统级工具无法直接统计物理SSD的真实IO数据:
- /proc/diskstats:WSL2中的块设备(如
/dev/sda)是对应Windows VHDX文件的虚拟磁盘,IO请求会先经过WSL2虚拟块层转发到Windows存储栈,所以/proc/diskstats统计的是虚拟设备的IO,而非物理SSD的,自然拿不到真实数据。 - perf工具:WSL2对perf的硬件性能事件支持有限,存储IO相关的事件无法穿透到Windows内核,导致返回0值。
可行解决方案
1. 直接在Windows环境测试物理SSD性能
- 用微软官方工具
diskspd.exe,命令示例:
该命令会测试F盘文件,持续30秒,用8线程、64KB块大小做随机读,直接输出吞吐量和IOPS。diskspd -d30 -c1G -t8 -o64 -r F:\testfile.dat - 也可以用CrystalDiskMark这类图形化工具快速验证物理SSD的基准性能。
2. 启用WSL2直接存储访问(谨慎操作)
Windows 11 22H2及以上版本支持直接挂载物理SSD到WSL2,步骤:
- 以管理员身份启动PowerShell,执行
Get-Disk查看物理SSD的编号(比如编号0)。 - 在用户目录下创建
.wslconfig文件,添加:[wsl2] disk=PhysicalDrive0 - 重启WSL:
wsl --shutdown,再重新启动WSL。
此时WSL会直接挂载物理SSD,/proc/diskstats就能统计到真实的IO数据,但此操作会绕过Windows文件系统,务必备份数据,避免误操作丢失文件。
3. 在程序内部直接统计吞吐量(最可靠)
不依赖系统工具,在你的io_uring读取逻辑中直接计时并统计读取字节数,示例代码调整:
#include <chrono> #include <spdlog/spdlog.h> // 假设你的io_uring读取函数返回总读取字节数 uint64_t readWithIoUring(const std::string& filePath) { // 你的io_uring读取逻辑实现 uint64_t totalBytes = 0; // ...完成读取后返回总字节数 return totalBytes; } int main() { const std::string filePath = "/path/to/your/target/file"; auto start = std::chrono::high_resolution_clock::now(); uint64_t totalBytes = readWithIoUring(filePath); auto end = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start); double throughput = static_cast<double>(totalBytes) / (duration.count() / 1e6); // 单位:B/s spdlog::info("Total bytes read: {}", totalBytes); spdlog::info("Duration: {} us", duration.count()); spdlog::info("Throughput: {:.2f} MB/s", throughput / (1024 * 1024)); return 0; }
这种方式完全不受WSL2虚拟化限制,能准确统计你的程序实际读取的吞吐量。
对你现有代码的补充说明
- 你代码中假设扇区大小为512字节是正确的,
/proc/diskstats中的sectors_read始终以512字节为单位计数,和物理扇区大小无关。 - 但核心问题还是WSL2的虚拟设备导致统计的不是物理SSD数据,所以即使代码逻辑正确,也拿不到真实值。
内容的提问来源于stack exchange,提问作者Dexter0411
相关产品推荐
相关产品推荐

