
最近在评估一批新上架的 NVMe SSD手里拿着 CrystalDiskMark 跑出来的几个数字总觉得说服不了自己。CrystalDiskMark 这类图形化工具适合快速看一眼盘有没有坏但它的测试模型太固定队列深度、块大小、读写比例都是预设的没法按我真实业务的负载去定制。真正要回答“这块盘能不能扛住这套业务”我一般直接用 diskspd微软开源的那款存储负载模拟工具。它门槛看着高全是命令行但一旦把参数逻辑理顺你会发现这才是 Windows 上做严谨磁盘压测最趁手的工具。这篇文章就围绕 diskspd 的日常使用把核心参数、常见测试场景、输出解读,以及我实际踩过的坑完整过一遍。适合两类人一类是刚要接触磁盘性能测试的运维和开发另一类是已经用 CrystalDiskMark 这类工具但想进一步验证存储性能、做前后对比测试的人。1. 为什么我最终选了 Diskspd 做磁盘压测1.1 市面上的工具各有各的局限说实话Windows 生态里的磁盘性能测试工具并不少。CrystalDiskMark 简单直观跑一遍能看到顺序读写和 4K 随机读写但它的队列深度、块大小、文件大小都是写死的适合做“大众点评式”的结果对比不适合模拟具体业务。AS SSD Benchmark 偏向 SSD 评分fio 在 Linux 上很强但在 Windows 上部署稍麻烦还要处理编译和依赖。diskspd 的优势在于微软官方出品开源参数设计严谨完全命令行驱动方便写脚本批量执行可以精确控制块大小、线程数、队列深度、读写比例、随机/顺序模式支持绕过操作系统缓存和硬件写缓存测出来的是设备真实能力支持输出延迟分位数数据库这类延迟敏感型业务非常看重这个。我用它验证过数据库服务器加盘、虚拟化平台的存储扩容、以及 SSD 固件升级前后的性能回归。每次都是先根据业务模型确定几组参数然后用一条命令跑到出结果留存记录沉淀成一套固定的压测流程。1.2 Diskspd 适合拿来回答哪些问题这块盘能不能达到厂家标称的标称 IOPS 和带宽同样的 RAID 策略下换盘或者改条带大小之后性能变化多少队列深度从 4 提到 16吞吐和延迟如何变化系统在混合读写场景下的性能表现而不是只看纯读或纯写一个存储卷的延迟分布在 p95、p99 是什么水平适不适合跑数据库。把这些典型问题映射到具体命令上就是我接下来要讲的参数用法。2. 拿到 Diskspd 之后先跑通这一条命令2.1 下载与安装的两种方式Diskspd 是绿色可执行文件不需要安装。从 GitHub 上 microsoft/diskspd 的 Releases 页面下载压缩包解压后 bin 目录下有 amd64、x86、arm64 等子目录按系统架构选一个。我习惯把整个目录放到 C:\Tools\Diskspd然后把目录加进 PATH。如果你只是临时用一次直接在 PowerShell 里用.\diskspd.exe指到相对路径也可以。注意如果命令里要用-S、-Sh这类绕过缓存的参数建议右键“以管理员身份运行”PowerShell 或 CMD。权限不够时部分设备控制指令不会生效测试结果看起来正常实际测的并不是你想测的东西。2.2 最小可用命令逐段拆解先看一条我经常用的基础命令.\diskspd.exe -Sh -c4G -d30 -t4 -o4 -b64K -w30 D:\io\testfile.dat这条命令的意思是在 D:\io 目录下创建一个 4GB 的测试文件 testfile.dat用 4 个线程、每个线程 4 个未完成 I/O相当于队列深度 16、每次读写 64KB、30% 写 70% 读持续跑 30 秒并且绕过软件缓存和硬件写缓存。逐段解释一下-Sh-S表示禁用操作系统软件缓存加上h后还会尽量禁用硬件写缓存。测试存储设备真实性能时我基本都带这个参数。-c4G创建 4GB 的测试文件。文件越大越能避免内存缓存的影响后面单独讲。-d30测试时长 30 秒。我建议正式测试至少 60 秒。-t4启动 4 个 worker 线程。-o4每个线程同时保持 4 个未完成的 I/O配合-t4就是 4 乘以 4 等于 16 的并发请求数。-b64K每次 I/O 的块大小。-w30写请求占比 30%。首次跑通后先看输出最前面的部分。如果显示Validation: successful说明参数没问题开始执行了。紧接着它会把本次测试的输入参数回显出来比如文件大小、块大小、线程数、队列深度、测试时间、写比例等。这一步不能跳着看很多人测完了才发现参数传错了等于白跑。2.3 常用参数速查表参数含义常见取值-b块大小4K、64K、1M-c测试文件大小4G、8G、16G-d测试时长30、60、300-w写请求百分比0、30、100-t线程数1、4、8、16-o每线程未完成 I/O 数1、4、8、32-r随机 I/O不加为顺序-S/-Sh禁用软件缓存 / 同时禁用硬件写缓存默认不加-L输出延迟分位数默认关闭-i结果采样间隔1000 毫秒这张表不需要背真正用熟了之后你会发现日常压测来来回回就是这几个参数在排列组合。3. 把核心参数映射到真实测试场景3.1 读写比例-w 决定测试模型-w后面跟 0 到 100 的整数100 表示纯写0 表示纯读。实际业务很少是纯粹的读或写但我们在压测时往往要拆开来看。比如要验证数据库磁盘的读性能我会跑-w0因为它测的是存储的读延迟底线。要模拟备份窗口的大流量写入就跑-w100看看持续写入时性能会不会衰减。要模拟 OLTP 混合负载可以按 70% 读、30% 写来设也就是-w30。这里有个容易被忽略的点SSD 的写入会触发垃圾回收和磨损均衡所以纯写测试的指标通常比混合读写更差而且持续写入一段时间后还可能因为缓存用尽而明显掉速。如果你想看一块盘的“真实底线”一定不能只跑短时间的纯写至少要跑到 300 秒以上并在结果里观察不同时间段的采样值。3.2 队列深度-t 和 -o 怎么配合队列深度这个概念网上解释很多我的类比是线程是柜台里的营业员队列深度是每个营业员手上同时能处理的订单数量。营业员越多、每个人手上订单越多整体吞吐越大但每个订单的等待时间也会变长。-t4 -o4和-t16 -o1的总未完成 I/O 数都是 16但表现会不同。前者是 4 个线程各自深排队后者是 16 个线程各自浅排队。前者更贴近传统数据库的 I/O 压力模型后者更贴近客户端数量多但单个客户端请求不深的场景。如果你想画一条队列深度和 IOPS 的关系曲线可以固定-t4把-o从 1 依次调到 4、8、16、32跑一组对照测试。这样能直观看到这块盘在什么深度下开始饱和饱和点的延迟是多少。3.3 块大小-b 的取舍逻辑块大小决定了每次 I/O 搬运多少数据。可以把存储系统想象成搬家公司搬运大箱子时效率高但灵活性差搬运小箱子时灵活但单位数据量的开销大。4K 块模拟数据库随机读写页大小常见为 8K但 4K 的随机压力在存储测试里更普遍64K 块文件系统中的普通文件读写兼顾 IOPS 和吞吐1M 块大文件复制、备份流、视频编辑这种持续大流量场景。块大小直接影响 IOPS 和吞吐量的换算关系吞吐量约等于 IOPS 乘以块大小。比如同样是 10 万 IOPS4K 块只有 390MB/s而 64K 块可以跑到 6250MB/s。所以压测报告里一定要同时写清楚块大小否则光说“IOPS 十万”没有任何意义。3.4 测试时长和采样-d的默认值是 10 秒但我不建议拿 10 秒就下结论。短时间测试可能正好命中 SSD 的 SLC 缓存也可能因为前面没有预热导致结果偏低。我一般遵循这个节奏快速摸底-d30正式验证-d120或-d300持续压力-d600以上观察后面几分钟是否掉速-i参数控制采样间隔默认是 1000 毫秒也就是每秒输出一行中间结果。这个中间结果很有用你可以看到写入速度是不是从第一秒就开始下滑。如果前 30 秒稳定在 2GB/s后面慢慢掉到 1.2GB/s说明这块盘用的是 SLC 缓存策略缓存耗尽后的表现才是你以后实际能享受到的性能。4. 缓存对测试结果的干扰和应对4.1 -S 和 -Sh绕过缓存是压测的第一原则Windows 默认会把文件读写放一部分到内存里缓存被缓存命中的读写会快得离谱但不是磁盘的真实水平。如果测试文件只有 1GB机器内存 64GB整块文件都能被塞进内存测出来的“磁盘性能”实际上是内存性能。-S参数让 diskspd 以无缓冲方式打开文件绕过操作系统软件缓存。-Sh在它的基础上还会尝试关闭硬件写缓存。我在测试里基本统一用-Sh这样才能看到设备本身的表现。有一点要说明-S和-Sh绕过的是缓存路径但如果测试文件太小仍然会受其他层面的干扰比如 SSD 内部的小块映射表、写缓冲等。所以文件大小不能省。4.2 测试文件大小怎么定测试文件大小至少要大于内存中可用的缓存空间。保守做法是测试文件大小 本机物理内存的两倍以上。比如 16GB 内存的机器测试文件至少 32GB。如果环境里还有其他应用占用内存还要再放大一些。另一个需要考虑的是 SSD 的写入缓存区大小。现在很多消费级 NVMe SSD 都有一段 SLC 缓存可能是 10GB 到几十 GB 不等。如果测试文件只有 4GB纯写测试可能全程都在 SLC 缓存里跑结果非常漂亮但真实使用中缓存一旦耗尽就是另一回事。我建议至少用 8GB 到 16GB 的测试文件来测写入场景。提示匹配业务模型也很重要。如果你要评估的是数据库数据盘通常建议测试文件大小大于热数据量而不是盲目追求大文件。超大文件的持续写测的是垃圾回收和稳态性能小文件测的是缓存性能两者回答的问题不同。4.3 硬件写缓存和权限问题硬盘和阵列卡通常有自己的写缓存尤其是带电池的 RAID 卡写缓存对提升写入性能帮助巨大。-Sh会尽量在逻辑上绕过硬件写缓存但有些设备不响应这个指令。旧版 diskspd 里的-D参数也会通过设备控制指令去关闭硬件写缓存不过大量 NVMe 盘并不支持这种操作具体要看设备固件。我的经验是命令一律加-Sh并且用管理员权限运行。如果怀疑结果仍然受到硬件写缓存影响可以对比同一条命令在“有缓存”和“无缓存”两种状态下的差异差异越大说明设备写缓存策略越激进。5. 输出结果怎么看这些数字才是关键5.1 四个核心指标diskspd 跑完后会输出一段汇总不同版本格式略有差异核心字段永远不会变指标含义什么时候看它IOPS每秒完成的 I/O 次数随机小 IO 场景比如数据库Throughput每秒传输的字节数大块顺序读写比如备份、视频Latency平均 / 最小 / 最大延迟所有场景尤其是写延迟分位数延迟p50 / p90 / p95 / p99数据库、消息队列等高敏感业务IOPS 和吞吐量是同一枚硬币的正反面。IOPS 高不代表吞吐量大带宽高也不代表能扛住高随机压力。我一般看场景OLTP 看 IOPS 和 p99 延迟文件传输类看吞吐混合业务两个都看。5.2 -L 分位数延迟比平均值重要得多不加-L时diskspd 只输出平均延迟。平均延迟的问题在于它会被大量低延迟请求拉低掩盖少量高延迟请求。比如 95% 的请求都是 2ms5% 的请求是 200ms平均值只有 11.9ms看起来还行但那个 200ms 的尖刺很可能就是数据库事务超时的元凶。加上-L之后输出会包含 p50、p90、p95、p99 等分位数延迟。我会重点关注 p99这个数能说明最差的一批请求延迟在什么水平。数据库选型时很多团队要求 p99 不超过 20ms那压测结果就必须要带-L才能支撑这个判断。5.3 一份示例输出逐行解读下面是我根据常见输出结构整理的一个示例Total IO threads: 4 blocksize: 65536 write ratio: 30% duration: 60.00s Total IO count: 746124 IOPS: 12435.4 Throughput: 760.20 MB/s Average latency: 4.12 ms Min latency: 0.08 ms Max latency: 192.45 ms Latency percentiles: 50th percentile: 3.21 ms 95th percentile: 11.88 ms 99th percentile: 38.74 ms先看 IOPS 和吞吐量是否自洽12435 IOPS 乘以 64KB约等于 760MB/s符合上面的 Throughput说明没有明显异常。再看平均延迟 4.12ms 其实是被大多数正常请求拉低的p99 已经到了 38.74msmax 甚至到 192ms。如果你拿这块盘跑数据库可能出现偶发慢查询单看平均值根本发现不了。这种分布我首先会怀疑两块盘组 RAID 产生的写惩罚或者测试期间后台有别的任务在抢 I/O。输出里如果带了采样间隔数据还要看时间维度比如前 10 秒吞吐 2GB/s后面 50 秒掉到 900MB/s结论就该写“该盘 SLC 缓存容量约 X缓外稳态写性能约为 X”。6. 我在实际压测中踩过的坑6.1 测试文件的位置比想象中更影响结果最典型的坑是把测试文件建在系统盘上结果压测的同时操作系统还在不停读写页面文件、日志和各种临时文件。系统盘的表现会被干扰得乱七八糟。测试目标盘应该尽量独立特别是测数据库数据盘时这台机器上就该有单独的测试卷。还有一个很隐蔽的问题测试目录所在的分区在物理盘上的位置会影响结果。机械盘的外圈速度比内圈快如果测试文件刚好落在盘片外圈顺序读写性能会偏高。SSD 虽然不存在外圈概念但闪存块的管理策略也会让不同区域的性能有差异。所以同一个盘的横向对比测试尽量保证测试文件用同一个路径、同一个大小。6.2 分区对齐问题Windows 7 时代之前的系统盘用 Ghost 克隆时经常会产生 31KB 偏移的分区4K 随机读写的性能被按在地上摩擦。后来 Windows 安装器默认从 1MB 边界对齐问题就不常见了。但老机器、异机迁移、第三方分区工具改过分区结构的情况仍然可能出现对齐偏移。我一般用 PowerShell 检查分区信息Get-Partition | Select-Object DiskNumber, PartitionNumber, DriveLetter, Offset, SizeOffset 能被 4096 整除是最基本要求能被 1MB1048576整除更理想。如果偏移不对重做分区比调任何参数都有效。这个问题在普通办公机上不易察觉在数据库加载场景下能让随机读性能掉 20% 到 30%。6.3 杀毒软件和索引服务的干扰Windows Defender 的实时保护会扫描几乎所有新建文件和读写操作。测试开始时 diskspd 会在目标盘创建一个大文件这个创建过程本身就会触发实时扫描导致测试结果里混入 CPU 和磁盘争用。跑正式测试前我建议把测试目录加入 Defender 排除项或者临时关闭实时保护。另外Windows Search 索引器、Storage Sense、计划任务里的磁盘碎片整理都可能在你测试时“恰好”出来跑一圈。跑完一轮后去任务管理器看一眼磁盘活动是否归零再跑下一轮。6.4 多轮测试和文件清理只跑一轮就下结论是压测里最常见的大忌。SSD 的写入性能受温度、缓存状态、垃圾回收进度影响同样的命令跑三轮结果可能差出 30%。我的习惯是每套参数至少跑三遍记录三次结果取中位数作为结论同时看最大值和最小值的差距。如果三轮结果波动很大先排查机器上有没有后台任务不要急着换参数。diskspd 用-c创建测试文件后不会自动删除。压测完毕记得清理否则一个 8GB 的测试文件占满磁盘下次测试结果又会受影响。我写脚本时会在测试结束后自动加一条删除命令Remove-Item D:\io\testfile.dat -Force -ErrorAction SilentlyContinue6.5 一套完整的多场景测试脚本最后分享一个我常用的最小测试矩阵覆盖了最常见的三类负载# 4K 随机读模拟数据库点查 .\diskspd.exe -Sh -c8G -d120 -t4 -o8 -b4K -w0 -L -i1000 D:\io\testfile.dat # 64K 混合读写模拟文件服务器 .\diskspd.exe -Sh -c8G -d120 -t8 -o8 -b64K -w30 -L -i1000 D:\io\testfile.dat # 1M 顺序写模拟备份和大文件落地 .\diskspd.exe -Sh -c8G -d120 -t4 -o4 -b1M -w100 -L -i1000 D:\io\testfile.dat这三条命令跑完你对一块盘的基本性格就有数了小 I/O 随机能力怎么样、混合负载延迟稳不稳、大块写入会不会掉速。如果需要更精确地模拟业务再按实际负载调整读写比例和队列深度。我个人在实际操作中的体会是diskspd 的价值不在于某一个具体数字有多漂亮而在于它能让你在真实业务上线之前用可控的方式把存储系统的脾气摸清楚。很多人觉得命令行工具吓人其实只要照着上面几条命令跑一遍很快就能建立起自己的判断标准。工具永远只是工具搞清楚每个参数在回答什么问题比记住一百条命令更有用。