使用 DISKSPD 测试工作负载存储性能 - Azure Local

适用范围

适用于:Azure Stack HCI,版本 22H2 和 21H2;Windows Server 2022,Windows Server 2019

重要提示

Azure Stack HCI 现在已成为 Azure Local 的一部分。然而,旧版本的 Azure Stack HCI,例如 22H2,将继续引用 Azure Stack HCI,不会反映名称更改。了解更多。

本文提供了使用 DISKSPD 测试工作负载存储性能的指导。如果你已经搭建好了一个 Azure Stack HCI 集群,准备就绪,那很好,但你如何知道是否获得了所承诺的性能指标,无论是延迟、吞吐量还是 IOPS 呢?这时你可能需要借助 DISKSPD。阅读完本文后,你将了解如何运行 DISKSPD、理解一组参数、解读输出结果,并对影响工作负载存储性能的变量有一个大致的了解。

DISKSPD 是什么?

DISKSPD 是一个用于微基准测试的 I/O 生成命令行工具。那么,这些术语是什么意思呢?任何搭建 Azure Stack HCI 集群或物理服务器的人都是有原因的。可能是为了搭建一个网络托管环境,或者为员工运行虚拟桌面。无论实际用例是什么,你可能都希望在部署实际应用程序之前进行模拟测试。然而,在真实场景中测试你的应用程序往往很困难,这时 DISKSPD 就派上用场了。

DISKSPD 是一个可以定制的工具,用于创建自己的合成工作负载,并在部署前测试你的应用程序。这个工具的酷炫之处在于,它允许你配置和调整参数,以创建一个特定场景,使其类似于你的真实工作负载。DISKSPD 可以让你在部署前了解你的系统能够达到的性能。其核心,DISKSPD 只是发出一系列读写操作。

现在你已经知道了 DISKSPD 是什么,但什么时候应该使用它呢?DISKSPD 在模拟复杂工作负载方面存在困难。但当你的工作负载不能通过单线程文件复制来近似时,你需要一个简单的工具来产生可接受的基线结果,这时 DISKSPD 就非常适用。

快速入门:安装和运行 DISKSPD

要安装并运行 DISKSPD,请以管理员身份打开管理 PC 上的 PowerShell,然后按照以下步骤操作:

  1. 要下载并解压 DISKSPD 工具的 ZIP 文件,请运行以下命令:
# 定义 ZIP 文件的 URL 和保存文件的完整路径,包括文件名
$zipName = "DiskSpd.zip"
$zipPath = "C:\DISKSPD"
$zipFullName = Join-Path $zipPath $zipName
$zipUrl = "https://github.com/microsoft/diskspd/releases/latest/download/" +$zipName

# 确保目标目录存在,如果不存在则创建
if (-Not (Test-Path $zipPath)) {
New-Item -Path $zipPath -ItemType Directory | Out-Null
}
# 下载并解压 ZIP 文件
Invoke-RestMethod -Uri $zipUrl -OutFile $zipFullName
Expand-Archive -Path $zipFullName -DestinationPath $zipPath
  1. 要将 DISKSPD 目录添加到你的 $PATH 环境变量中,请运行以下命令:
$diskspdPath = Join-Path $zipPath $env:PROCESSOR_ARCHITECTURE
if ($env:path -split ';' -notcontains $diskspdPath) {
$env:path += ";" + $diskspdPath
}
  1. 使用以下 PowerShell 命令运行 DISKSPD。将方括号替换为你的相应设置。
diskspd [INSERT_SET_OF_PARAMETERS] [INSERT_CSV_PATH_FOR_TEST_FILE] > [INSERT_OUTPUT_FILE.txt]

这里有一个你可以运行的示例命令:

diskspd -t2 -o32 -b4k -r4k -w0 -d120 -Sh -D -L -c5G C:\ClusterStorage\test01\targetfile\IO.dat > test01.txt

注意

如果你没有测试文件,请使用 -c 参数创建一个。如果你使用了这个参数,请确保在定义路径时包含测试文件名。例如:[INSERT_CSV_PATH_FOR_TEST_FILE] = C:\ClusterStorage\CSV01\IO.dat。在示例命令中,IO.dat 是测试文件名,test01.txt 是 DISKSPD 输出文件名。

指定关键参数

好吧,这很简单,对吧?不幸的是,这不仅仅是这些。让我们来剖析一下我们刚才做了什么。首先,有各种参数可以调整,而且可能会很具体。然而,我们使用了以下一组基线参数:

注意

DISKSPD 参数区分大小写。

-t2:这表示每个目标/测试文件的线程数。这个数字通常基于 CPU 核心数。在这个例子中,使用了两个线程来压力测试所有 CPU 核心。

-o32:这表示每个目标每个线程的未完成 I/O 请求的数量。这也就是所谓的队列深度,在这个例子中,使用了 32 个来压力测试 CPU。

-b4K:这表示块大小,单位为字节、KiB、MiB 或 GiB。在这个例子中,使用了 4K 块大小来模拟随机 I/O 测试。

-r4K:这表示随机 I/O 对齐到指定的大小,单位为字节、KiB、MiB、Gib 或块(覆盖 -s 参数)。使用了常见的 4K 字节大小来正确对齐块大小。

-w0:这指定了写请求的操作百分比(-w0 相当于 100% 读取)。在这个例子中,使用了 0% 写入来进行一个简单的测试。

-d120:这指定了测试的持续时间,不包括冷却或预热时间。默认值是 10 秒,但我们建议对于任何严肃的工作负载至少使用 60 秒。在这个例子中,使用了 120 秒来最小化任何异常值。

-Suw:禁用软件和硬件写入缓存(等同于 -Sh)。

-D:捕获 IOPS 统计数据,例如标准差,以毫秒为间隔(每个线程,每个目标)。

-L:测量延迟统计数据。

-c5g:设置测试中使用的样本文件大小。它可以设置为字节、KiB、MiB、GiB 或块。在这个例子中,使用了 5GB 的目标文件。

要查看完整的参数列表,请参阅 GitHub 仓库。

了解环境

性能在很大程度上取决于你的环境。那么,我们的环境是什么样的呢?我们的规格涉及一个带有存储池和 Storage Spaces Direct(S2D)的 Azure Stack HCI 集群。更具体地说,有五个虚拟机:DC、node1、node2、node3 和管理节点。集群本身是一个三节点集群,采用三向镜像弹性结构。因此,维护了三个数据副本。集群中的每个“节点”都是一个 Standard_B2ms 虚拟机,其最大 IOPS 限制为 1920。在每个节点内,有四个高级 P30 SSD 驱动器,其最大 IOPS 限制为 5000。最后,每个 SSD 驱动器有 1TB 的内存。

你在 Cluster Shared Volume(CSV)提供的统一命名空间下生成测试文件(C:\ClusteredStorage),以便使用整个驱动器池。

注意

示例环境没有 Hyper-V 或嵌套虚拟化结构。

正如你将看到的,完全有可能独立达到 VM 或驱动器限制的 IOPS 或带宽上限。因此,了解你的 VM 大小和驱动器类型很重要,因为它们都有一个最大 IOPS 限制和带宽上限。这些知识有助于定位瓶颈并理解你的性能结果。要了解更多关于适合你的工作负载的大小,请参阅以下资源:

  • 虚拟机大小
  • 磁盘类型

理解输出

现在你已经了解了参数和环境,就可以解读输出结果了。首先,前面测试的目标是最大化 IOPS,而不考虑延迟。这样,你可以直观地看到是否在 Azure 内达到了人为的 IOPS 限制。如果你想以图形方式可视化总 IOPS,可以使用 Windows Admin Center 或任务管理器。

以下图表展示了在我们的示例环境中 DISKSPD 进程的样子。它显示了一个来自非协调节点的 1MiB 写入操作的示例。三向弹性结构,加上来自非协调节点的操作,导致了两次网络跳转,降低了性能。如果你想知道什么是协调节点,别担心!你将在“注意事项”部分了解它。红色正方形代表 VM 和驱动器瓶颈。

img

现在你已经对它有了直观的了解,让我们来检查一下 .txt 文件输出的四个主要部分:

  1. 输入设置

这个部分描述了你运行的命令、输入参数以及有关测试运行的其他详细信息。

img

  1. CPU 使用情况细节

这个部分突出了诸如测试时间、线程数量、可用处理器数量以及测试期间每个 CPU 核心的平均利用率等信息。在这个例子中,两个 CPU 核心的平均使用率约为 4.67%。

img

  1. 总 I/O

这个部分有三个子部分。第一部分突出了包括读写操作在内的整体性能数据。第二部分和第三部分将读写操作分别归类。

在这个例子中,你可以看到在 120 秒的持续时间内,总 I/O 次数为 234408。因此,IOPS = 234408 /120 = 1953.30。平均延迟为 32.763 毫秒,吞吐量为 7.63 MiB/s。从前面的信息中,我们知道 1953.30 IOPS 接近我们 Standard_B2ms 虚拟机的 1920 IOPS 限制。不相信吗?如果你使用不同的参数重新运行这个测试,比如增加队列深度,你会发现结果仍然被限制在这个数字。

最后三列显示了 IOPS 的标准差为 17.72(来自 -D 参数),延迟的标准差为 20.994 毫秒(来自 -L 参数),以及文件路径。

img

从结果中,你可以很快地判断出集群配置很糟糕。你可以看到它在达到 SSD 的 5000 限制之前就达到了虚拟机的 1920 限制。如果你受到 SSD 而不是虚拟机的限制,你就可以通过将测试文件跨越多个驱动器来利用多达 20000 IOPS(4 个驱动器 * 5000)。

最终,你需要决定对你特定工作负载来说哪些值是可以接受的。下图显示了一些重要的关系,帮助你考虑权衡:

img

图中的第二个关系很重要,有时被称为 Little 定律。该定律引入了一个观点,即有三个特征支配进程行为,你只需要改变其中一个就可以影响其他两个,从而影响整个进程。因此,如果你对系统的性能不满意,你有三个维度的自由度来影响它。在我们的例子中,Little 定律规定 IOPS 是“吞吐量”(每秒输入输出操作次数),延迟是“队列时间”,队列深度是“库存”。

  1. 延迟百分位分析

最后一部分详细说明了从最小值到最大值的每种操作类型的存储性能延迟百分位。

这个部分很重要,因为它决定了你的 IOPS 的“质量”。它揭示了有多少 I/O 操作能够达到一定的延迟值。由你来决定那个百分位的可接受延迟是多少。

此外,“九”指的是九的数量。例如,“3 个九”相当于 99 百分位。九的数量暴露了在那个百分位运行的 I/O 操作的数量。最终,你会达到一个点,不再认真对待延迟值。在这个例子中,你可以看到在“4 个九”之后延迟值保持不变。在这个点上,延迟值仅基于 234408 次操作中的 1 次 I/O 操作。

img

注意事项

现在你已经开始使用 DISKSPD 了,为了获得真实世界中的测试结果,有几件事情需要考虑。这些包括密切关注你设置的参数、存储空间的健康状况和变量、CSV 所有权以及 DISKSPD 和文件复制之间的区别。

DISKSPD 与现实世界

DISKSPD 的人工测试可以为你的真实工作负载提供相对可比的结果。然而,你需要密切关注你设置的参数以及它们是否符合你的实际场景。重要的是要明白,合成工作负载永远不会完美地代表你的应用程序在部署期间的真实工作负载。

准备工作

在运行 DISKSPD 测试之前,有一些推荐的操作。这些包括验证存储空间的健康状况、检查你的资源使用情况,以确保没有其他程序干扰测试,并准备性能管理器,如果你想要收集额外的数据。然而,由于本文的目标是快速启动 DISKSPD,因此没有深入探讨这些操作的具体内容。要了解更多信息,请参阅使用合成工作负载在 Windows Server 中测试存储空间性能。

影响性能的变量

存储性能是一个微妙的事情。也就是说,有许多变量可能会影响性能。因此,你可能会遇到一些与你的预期不一致的数字。以下突出显示了一些影响性能的变量,尽管这不是一个全面的列表:

  • 网络带宽
  • 弹性选择
  • 存储磁盘配置:NVME、SSD、HDD
  • I/O 缓冲区
  • 缓存
  • RAID 配置
  • 网络跳数
  • 硬盘转速

CSV 所有权

一个节点被称为卷所有者或“协调”节点(非协调节点则是不拥有特定卷的节点)。每个标准卷都被分配了一个节点,其他节点可以通过网络跳转访问这个标准卷,这会导致性能降低(延迟更高)。

同样,Cluster Shared Volume(CSV)也有一个“所有者”。然而,CSV 是“动态”的,因为它会在你每次重启系统(RDP)时改变所有权并跳转。因此,重要的是要确认 DISKSPD 是从拥有 CSV 的协调节点运行的。如果不是,你可能需要手动更改 CSV 的所有权。

要确认 CSV 所有权:

  1. 通过运行以下 PowerShell 命令检查所有权:
Get-ClusterSharedVolume
  1. 如果 CSV 所有权不正确(例如,你在 Node1 上,但 Node2 拥有 CSV),则通过运行以下 PowerShell 命令将 CSV 移动到正确的节点:
Get-ClusterSharedVolume <INSERT_CSV_NAME> | Move-ClusterSharedVolume <INSERT_NODE_NAME>

文件复制与 DISKSPD

有些人认为他们可以通过复制和粘贴一个巨大的文件并测量该过程所需的时间来“测试存储性能”。这种方法背后的主要原因可能是因为它简单且快速。从某种意义上说,这个想法并不错误,因为它测试了一个特定的工作负载,但很难将这种方法归类为“测试存储性能”。

如果你的真实目标是测试文件复制性能,那么这可能是一个完全有效的使用这种方法的原因。然而,如果你的目标是衡量存储性能,我们建议不要使用这种方法。你可以将文件复制过程视为使用了一组特定于文件服务的“参数”(例如队列、并行化等)。

以下简要总结了为什么使用文件复制来衡量存储性能可能无法提供你想要的结果:

  • 文件复制可能没有优化:存在两个层面的并行性,一个内部的,另一个外部的。内部来说,如果文件复制的目标是远程目标,CopyFileEx 引擎确实会应用一些并行化。外部来说,调用 CopyFileEx 引擎有不同方式。例如,从文件资源管理器复制是单线程的,但 Robocopy 是多线程的。因此,重要的是要了解测试的含义是否符合你的需求。

  • 每次复制都有两个方面:当你复制和粘贴一个文件时,你可能会使用两个磁盘:源磁盘和目标磁盘。如果其中一个比另一个慢,你实际上测量的是较慢磁盘的性能。还有其他情况下,源、目标和复制引擎之间的通信可能会以独特的方式影响性能。

要了解更多信息,请参阅使用文件复制来衡量存储性能。

实验和常见工作负载

本节包括一些其他示例、实验和工作负载类型。

确认协调节点

如前所述,如果你正在测试的 VM 不拥有 CSV,你会看到性能下降(IOPS、吞吐量和延迟),与节点拥有 CSV 时进行测试相比。这是因为每次你发出一个 I/O 操作时,系统都会进行一次网络跳转到协调节点来执行该操作。

对于三节点、三向镜像的情况,写入操作总是会进行一次网络跳转,因为它需要在三个节点的所有驱动器上存储数据。因此,无论使用何种弹性结构,写入操作都会进行网络跳转。

以下是一个示例:

  • 在本地节点运行:diskspd.exe -t4 -o32 -b4k -r4k -w0 -Sh -D -L C:\ClusterStorage\test01\targetfile\IO.dat
  • 在非本地节点运行:diskspd.exe -t4 -o32 -b4k -r4k -w0 -Sh -D -L C:\ClusterStorage\test01\targetfile\IO.dat

从下面的图表结果中,你可以清楚地看到,当协调节点拥有 CSV 时,延迟降低,IOPS 增加,吞吐量增加。

在线事务处理(OLTP)工作负载

在线事务处理(OLTP)工作负载查询(更新、插入、删除)侧重于事务导向的任务。与在线分析处理(OLAP)相比,OLTP 取决于存储延迟。因为每个操作发出的 I/O 很少,所以你关心的是每秒可以持续进行多少次操作。

你可以设计一个 OLTP 工作负载测试,专注于随机的小 I/O 性能。对于这些测试,专注于在保持可接受延迟的同时,可以推动吞吐量达到多远。

这种工作负载测试的基本设计选择至少应包括:

  • 8KB 块大小 => 类似于 SQL Server 为其数据文件使用的页面大小
  • 70% 读取,30% 写入 => 类似于典型的 OLTP 行为

在线分析处理(OLAP)工作负载

OLAP 工作负载侧重于数据检索和分析,允许用户执行复杂查询以提取多维数据。与 OLTP 相反,这些工作负载对存储延迟并不敏感。它们强调排队许多操作,而不怎么关心带宽。因此,OLAP 工作负载通常会导致处理时间更长。

你可以设计一个 OLAP 工作负载测试,专注于顺序的大 I/O 性能。对于这些测试,专注于每秒处理的数据量,而不是 IOPS 数量。延迟要求也不重要,但这取决于主观判断。

这种工作负载测试的基本设计选择至少应包括:

  • 512KB 块大小 => 类似于 SQL Server 在使用读取提前技术为表扫描加载一批 64 个数据页时的 I/O 大小。

  • 每个文件 1 个线程 => 目前,你需要将测试限制为每个文件一个线程,因为当测试多个顺序线程时,DISKSPD 可能会出现问题。
    如果你使用了多个线程,比如说两个,并且使用了 -s 参数,线程将在同一个位置非确定性地发出 I/O 操作。这是因为它们各自跟踪自己的顺序偏移量。

有两种“解决方案”可以解决这个问题:

  • 第一种解决方案涉及使用 -si 参数。使用这个参数时,两个线程共享一个单一的互锁偏移量,以便线程可以合作地向目标文件发出单一的顺序访问模式。这允许文件中的任何一个点都不会被操作超过一次。然而,由于它们仍然会相互竞争将它们的 I/O 操作放入队列,因此操作可能会无序到达。

    如果一个线程受到 CPU 限制,这种解决方案效果很好。你可能希望在第二个 CPU 核心上启动第二个线程,以向 CPU 系统提供更多存储 I/O,从而进一步饱和它。

  • 第二种解决方案涉及使用 -T<偏移量>。这允许你指定不同线程在同一个目标文件上执行 I/O 操作之间的偏移量大小(I/O 间隙)。例如,线程通常从偏移量 0 开始,但这个规范允许你将两个线程分开,使它们不会重叠。在任何多线程环境中,线程可能位于目标工作区的不同部分,这是一种模拟这种情况的方法。

posted @ 2025-05-22 09:38  LoftyAmbition  阅读(311)  评论(0)    收藏  举报