文章
· 二月 3, 2023 阅读大约需 5 分钟

PerfTools IO 测试套件

目的

这两个工具(RanRead 和 RanWrite)用于在数据库(或一对数据库)内生成随机读写事件,以测试每秒输入/输出的操作数 (IOPS)。它们可以一起使用或分开单独使用,以测试 IO 硬件容量、验证目标 IOPS 并确保系统拥有可接受的磁盘响应时间。从 IO 测试中收集的结果将因配置而异,具体取决于 IO 子系统。在运行这些测试之前,请确保相应的操作系统监控和存储级别监控已配置,这些捕获的 IO 性能指标可以为以后的分析提供帮助。我们推荐使用 IRIS 中捆绑的系统性能工具,例如^SystemPerformance。

请注意,这里使用的工具是对先前版本的更新。之前的版本可在这里找到。

安装

从 GitHub 下载 PerfTools.RanRead.xmlPerfTools.RanWrite.xml 工具 点击这里

将工具导入 USER 命名空间。

USER> do $system.OBJ.Load("/tmp/PerfTools.RanRead.xml","ckf")
USER> do $system.OBJ.Load("/tmp/PerfTools.RanWrite.xml","ckf")

运行帮助方法以查看所有入口点。所有命令都在 USER 中运行。

USER> do ##class(PerfTools.RanRead).Help()
  • do ##class(PerfTools.RanRead).Setup(Directory,DatabaseName,SizeGB,LogLevel)
    创建具有相同名称的数据库和命名空间。日志级别必须在 0 到 3 的范围内,其中 0 是“无”,3 是“详细”。

  • do ##class(PerfTools.RanRead).Run(Directory,Processes,Count,Mode)
    运行随机读取 IO 测试。模式参数,1(默认)代表时间,以秒为单位 ,2是循环次数,用前面的 Count 参数控制。

  • do ##class(PerfTools.RanRead).Stop()
    终止所有后台作业。

  • do ##class(PerfTools.RanRead).Reset()
    删除先前运行的统计信息。在测试之间运行这个很重要,否则之前运行的统计数据将平均到当前运行的统计数据中。

  • do ##class(PerfTools.RanRead).Purge(Directory)
    删除同名的命名空间和数据库。

  • do ##class(PerfTools.RanRead).Export(Directory)
    将所有随机读取测试历史的摘要导出到逗号分隔的文本文件。

USER> do ##class(PerfTools.RanWrite).Help()
  • do ##class(PerfTools.RanWrite).Setup(Directory,DatabaseName)
    创建具有相同名称的数据库和命名空间。

  • do ##class(PerfTools.RanWrite).Run(Directory,NumProcs,RunTime,HangTime,HangVariationPct,Global name length,Global node depth,Global subnode length)
    运行随机写入 IO 测试。除目录外的所有参数都有默认值。

  • do ##class(PerfTools.RanWrite).Stop()
    终止所有后台作业。

  • do ##class(PerfTools.RanWrite).Reset()
    删除先前运行的统计信息。

  • do ##class(PerfTools.RanWrite).Purge(Directory)
    删除同名的命名空间和数据库。

  • do ##class(PerfTools.RanWrite).Export(Directory)
    将所有随机写入测试历史的摘要导出到逗号分隔的文本文件。

配置

创建一个名为 RAN 的空(预扩展)数据库,其大小至少是要测试的物理主机内存的两倍。同时确保这个空数据库至少是存储控制器缓存大小的四倍。数据库需要大于物理内存以确保读取的数据不会缓存在文件系统缓存中。您可以手动创建或使用以下方法自动创建命名空间和数据库。

USER> do ##class(PerfTools.RanRead).Setup("/ISC/tests/TMP","RAN",200,1)

Created directory /ISC/tests/TMP/  
Creating 200GB database in /ISC/tests/TMP/  
Database created in /ISC/tests/TMP/

注意:RanRead 和 RanWrite 可以使用相同的数据库。如果需要一次测试多个磁盘或用于特定目的,也可以使用分开的数据库。 RanRead 代码允许指定数据库的大小,但 RanWrite 代码不允许,因此最好使用 RanRead Setup 命令来创建所需的任何预先确定大小的数据库,即使要创建 RanWrite 做测试的数据库也可以。

方法论

从少量进程和 30-60 秒运行时间开始测试。然后增加进程数,例如从 10 个作业开始,然后增加 10、20、40 等。继续运行单个测试,直到响应时间始终超过 10 毫秒或计算出的 IOPS 不再以线性方式增加。

该工具使用 ObjectScript VIEW 命令读取内存中的数据库块,因此如果您没有获得预期的结果,则可能所有数据库块都已在内存中。

作为指南,全闪存阵列通常可以接受以下 8KB 和 64KB 数据库随机读取(非缓存)的响应时间:

  • 平均 <= 2ms
  • 不超过 <= 5ms

运行

对于 RanRead,执行 Run 方法,逐渐增加进程数并在运行时记录响应时间。 RanRead IOPS 的主要驱动因素是进程数。

USER> do ##class(PerfTools.RanRead).Run("/ISC/tests/TMP",5,60)

InterSystems Random Read IO Performance Tool  
--------------------------------------------  
RanRead process 11742 creating 5 worker processes in the background.  
  Prepped RanReadJob 11768 for parent 11742  
  Prepped RanReadJob 11769 for parent 11742  
  Prepped RanReadJob 11770 for parent 11742  
  Prepped RanReadJob 11771 for parent 11742  
  Prepped RanReadJob 11772 for parent 11742  
Starting 5 processes for RanRead job number 11742 now!  
To terminate run:  do ##class(PerfTools.RanRead).Stop()  
Waiting to finish...............................................................  
Random read background jobs finished for parent 11742  
RanRead job 11742's 5 processes (62.856814 seconds) average response time = 1.23ms  
Calculated IOPS for RanRead job 11742 = 4065 

Run 命令的 Mode 参数默认为模式 1,它使用 Count 参数(上例中的 60)作为秒。将 Mode 设置为 2 会将 Count 参数读取为每个进程的循环次数,因此如果将其设置为 100,000,则 5 个作业中的每一个进程都将从数据库中读取 100,000 次。模式2是该软件最初使用的模式,但定时运行允许与监控工具(例如^SystemPerformance)和 RanWrite 工具进行更精确的协调,因为这些工具也是定时运行的。

对于 RanWrite,执行 Run 方法,逐渐减少 Hangtime 参数。该参数代表每次写入之间的等待时间(以秒为单位),并且是 RanWrite IOPS 的主要驱动因素。您也可以增加进程数作为 IOPS 的驱动因素。

USER> do ##class(PerfTools.RanWrite).Run("/ISC/tests/TMP",1,60,.001)

RanWrite process 11742 creating 1 worker processes in the background.  
  Prepped RanWriteJob 12100 for parent 11742  
Starting 1 processes for RanWrite job number 11742 now!  
To terminate run:  do ##class(PerfTools.RanWrite).Stop()  
Waiting to finish...............................................................  
Random write background jobs finished for parent 11742  
RanWrite job 11742's 1 processes (60 seconds) had average response time = .912ms  
Calculated IOPS for RanWrite job 11742 = 1096 

RanWrite 的其他参数通常可以保留默认值(除了极特殊情况)。这些参数是:
- HangVariationPct:Hangtime参数的方差,用于模拟不确定性;它是Hangtime参数的百分比
- Global name length:RanWrite 随机选择一个Global名称,这个参数是该名称的长度。例如,如果它设置为 6,Global可能会是 Xr6opg
- Global node depth and Global subnode length:最上层的Global不是真正会填充数据的,实际填充的是它的子节点,因此将这些值设置为 2 和 4 将产生类似“set ^Xr6opg("drb7","xt8v") = [value]”的命令。这两个参数和 Global name length 的目的都是为了确保不会一遍又一遍地填充相同的Global,填充相同的Global会导致最少的 IO 事件。

为了能一起运行 RanRead 和 RanWrite,不要使用“do”命令。使用“job”命令在后台运行它们。

结果

为了获取保存在 USER命名空间 SQL 表 PerfTools.RanRead 和 PerfTools.RanWrite 中的每次测试运行的结果,请对每个工具使用Export命令,如下所示。

要将结果集导出到逗号分隔的文本文件 (csv),请运行以下命令:

USER> do ##class(PerfTools.RanRead).Export("/ISC/tests/TMP/ ")

Exporting summary of all random read statistics to /usr/iris/db/zranread/PerfToolsRanRead_20221023-1408.txt  
Done.

分析

建议使用内置的 SystemPerformance 工具来获取被分析的系统的真实情况。 SystemPerformance 的命令需要在 %SYS 命名空间中运行。要切换到那个命名空间,请使用 ZN 命令:

USER> ZN "%SYS"

要查找系统瓶颈的详细信息,或者如果需要系统如何以目标 IOPS 运行的更多详细信息,则应创建具有高频率数据采集的 SystemPerformance 配置文件:

%SYS> set rc=$$addprofile^SystemPerformance("5minhighdef","A 5-minute run sampling every second",1,300)

然后运行该配置文件(从 %SYS)并立即切换回 USER 并使用“job”而不是“do”来启动 RanRead 和/或 RanWrite:

%SYS> set runid=$$run^SystemPerformance("5minhighdef")
%SYS> ZN “USER”
USER> job ##class(PerfTools.RanRead).Run("/ISC/tests/TMP",5,60)
USER> job ##class(PerfTools.RanWrite).Run("/ISC/tests/TMP",1,60,.001)

然后可以等待 SystemPerformance 作业结束,并使用 yaspe 等工具分析生成的 html 文件。

清理

运行完测试后,需要删除历史记录:

%SYS> do ##class(PerfTools.RanRead).Reset()
讨论 (0)1
登录或注册以继续