diff --git a/src/VirtualClient/VirtualClient.Actions.UnitTests/DiskSpd/DiskSpdMetricsParserTests.cs b/src/VirtualClient/VirtualClient.Actions.UnitTests/DiskSpd/DiskSpdMetricsParserTests.cs index 3470b9ed08..71cb724f17 100644 --- a/src/VirtualClient/VirtualClient.Actions.UnitTests/DiskSpd/DiskSpdMetricsParserTests.cs +++ b/src/VirtualClient/VirtualClient.Actions.UnitTests/DiskSpd/DiskSpdMetricsParserTests.cs @@ -199,6 +199,43 @@ public void DiskSpdParserVerifyWriteOnly() MetricAssert.Exists(metrics, "total latency max", 159.270, "ms"); } + [Test] + public void DiskSpdParserVerifyWriteOnlyV220FormatWithSocketNodeCoreColumns() + { + // DiskSpd v2.2.0 changed the CPU table to include Socket | Node | Group | Core | CPU columns. + // The parser must normalise this extended header without throwing a KeyNotFoundException. + string results = File.ReadAllText(MockFixture.GetDirectory(typeof(DiskSpdMetricsParserTests), "Examples", "DiskSpd", "DiskSpdExample-WriteOnly-v2.2.0.txt")); + var parser = new DiskSpdMetricsParser(results, "diskspd.exe -b4K -r4K -t160 -o3 -w100 -d900 -Suw -W15 -D -L -Rtext D:\\diskspd-test.dat"); + + IList metrics = parser.Parse(); + + // cpu metrics – rows 0,1 and avg from the truncated table + MetricAssert.Exists(metrics, "cpu usage 0", 98.74, "percentage"); + MetricAssert.Exists(metrics, "cpu usage 1", 98.69, "percentage"); + MetricAssert.Exists(metrics, "cpu usage average", 98.59, "percentage"); + MetricAssert.Exists(metrics, "cpu user average", 0.75, "percentage"); + MetricAssert.Exists(metrics, "cpu kernel average", 97.84, "percentage"); + + // Total IO + MetricAssert.Exists(metrics, "total bytes 0", 9466327040, "bytes"); + MetricAssert.Exists(metrics, "total throughput 0", 10.03, "MiB/s"); + MetricAssert.Exists(metrics, "total iops 0", 2567.89, "iops"); + MetricAssert.Exists(metrics, "total bytes total", 8265251819520, "bytes"); + MetricAssert.Exists(metrics, "total throughput total", 8758.14, "MiB/s"); + MetricAssert.Exists(metrics, "total iops total", 2242082.85, "iops"); + + // Write IO + MetricAssert.Exists(metrics, "write bytes total", 8265251819520, "bytes"); + MetricAssert.Exists(metrics, "write throughput total", 8758.14, "MiB/s"); + MetricAssert.Exists(metrics, "write iops total", 2242082.85, "iops"); + + // Latency + MetricAssert.Exists(metrics, "write latency min", 0.013, "ms"); + MetricAssert.Exists(metrics, "write latency 50th", 0.146, "ms"); + MetricAssert.Exists(metrics, "write latency 99th", 12.018, "ms"); + MetricAssert.Exists(metrics, "total latency max", 5543.894, "ms"); + } + [Test] public void DiskSpdParserVerifyForCoreCountGreaterThan64WhichAddsProcessorGrouping() { diff --git a/src/VirtualClient/VirtualClient.Actions.UnitTests/Examples/DiskSpd/DiskSpdExample-WriteOnly-v2.2.0.txt b/src/VirtualClient/VirtualClient.Actions.UnitTests/Examples/DiskSpd/DiskSpdExample-WriteOnly-v2.2.0.txt new file mode 100644 index 0000000000..c977f6c75e --- /dev/null +++ b/src/VirtualClient/VirtualClient.Actions.UnitTests/Examples/DiskSpd/DiskSpdExample-WriteOnly-v2.2.0.txt @@ -0,0 +1,97 @@ + +Command Line: C:\VirtualClient\content\win-x64\packages\diskspd.2.2.0\win-x64\diskspd.exe -c496G -b4K -r4K -t160 -o3 -w100 -d900 -Suw -W15 -D -L -Rtext D:\diskspd-test.dat + +Input parameters: + + timespan: 1 + ------------- + duration: 900s + warm up time: 15s + cool down time: 0s + measuring latency + gathering IOPS at intervals of 1000ms + random seed: 0 + path: 'D:\diskspd-test.dat' + think time: 0ms + burst size: 0 + software cache disabled + hardware write cache disabled, writethrough on + performing write test + block size: 4KiB + using random I/O (alignment: 4KiB) + number of outstanding I/O operations per thread: 3 + threads per file: 160 + using I/O Completion Ports + IO priority: normal + +System information: + + computer name: SCHIELC41ABD017 + start time: 2026/05/22 07:21:47 UTC + + cpu count: 320 + core count: 160 + group count: 5 + node count: 4 + socket count: 2 + heterogeneous cores: n + +Results for timespan 1: +******************************************************************************* + +actual test time: 900.00s +thread count: 800 + +Socket | Node | Group | Core | CPU | Usage | User | Kernel | Idle +----------------------------------------------------------------------- + 0| 0| 0| 0| 0| 98.74%| 0.89%| 97.85%| 1.26% + 0| 0| 0| 0| 1| 98.69%| 0.89%| 97.79%| 1.31% + 0| 0| 0| 1| 2| 99.98%| 0.87%| 99.11%| 0.02% + 0| 0| 0| 1| 3| 100.00%| 0.94%| 99.06%| 0.00% +----------------------------------------------------------------------- + avg.| 98.59%| 0.75%| 97.84%| 1.41% + +Total IO +thread | bytes | I/Os | MiB/s | I/O per s | AvgLat | IopsStdDev | LatStdDev | file +------------------------------------------------------------------------------------------------------------------ + 0 | 9466327040 | 2311115 | 10.03 | 2567.89 | 0.974 | 432.90 | 2.469 | D:\diskspd-test.dat (496GiB) + 1 | 9458679808 | 2309248 | 10.02 | 2565.82 | 0.970 | 437.51 | 2.456 | D:\diskspd-test.dat (496GiB) +------------------------------------------------------------------------------------------------------------------ +total: 8265251819520 | 2017883745 | 8758.14 | 2242082.85 | 0.861 | 135948.98 | 3.327 + +Read IO +thread | bytes | I/Os | MiB/s | I/O per s | AvgLat | IopsStdDev | LatStdDev | file +------------------------------------------------------------------------------------------------------------------ + 0 | 0 | 0 | 0.00 | 0.00 | 0.000 | 0.00 | N/A | D:\diskspd-test.dat (496GiB) + 1 | 0 | 0 | 0.00 | 0.00 | 0.000 | 0.00 | N/A | D:\diskspd-test.dat (496GiB) +------------------------------------------------------------------------------------------------------------------ +total: 0 | 0 | 0.00 | 0.00 | 0.000 | 0.00 | N/A + +Write IO +thread | bytes | I/Os | MiB/s | I/O per s | AvgLat | IopsStdDev | LatStdDev | file +------------------------------------------------------------------------------------------------------------------ + 0 | 9466327040 | 2311115 | 10.03 | 2567.89 | 0.974 | 432.90 | 2.469 | D:\diskspd-test.dat (496GiB) + 1 | 9458679808 | 2309248 | 10.02 | 2565.82 | 0.970 | 437.51 | 2.456 | D:\diskspd-test.dat (496GiB) +------------------------------------------------------------------------------------------------------------------ +total: 8265251819520 | 2017883745 | 8758.14 | 2242082.85 | 0.861 | 135948.98 | 3.327 + + + +total: + %-ile | Read (ms) | Write (ms) | Total (ms) +---------------------------------------------- + min | N/A | 0.013 | 0.013 + 25th | N/A | 0.080 | 0.080 + 50th | N/A | 0.146 | 0.146 + 75th | N/A | 0.470 | 0.470 + 90th | N/A | 1.683 | 1.683 + 95th | N/A | 3.151 | 3.151 + 99th | N/A | 12.018 | 12.018 +3-nines | N/A | 37.418 | 37.418 +4-nines | N/A | 62.504 | 62.504 +5-nines | N/A | 77.135 | 77.135 +6-nines | N/A | 148.814 | 148.814 +7-nines | N/A | 2247.379 | 2247.379 +8-nines | N/A | 5497.506 | 5497.506 +9-nines | N/A | 5543.894 | 5543.894 + max | N/A | 5543.894 | 5543.894 diff --git a/src/VirtualClient/VirtualClient.Actions/DiskSpd/DiskSpdMetricsParser.cs b/src/VirtualClient/VirtualClient.Actions/DiskSpd/DiskSpdMetricsParser.cs index 9368d28571..dddf925daa 100644 --- a/src/VirtualClient/VirtualClient.Actions/DiskSpd/DiskSpdMetricsParser.cs +++ b/src/VirtualClient/VirtualClient.Actions/DiskSpd/DiskSpdMetricsParser.cs @@ -111,7 +111,28 @@ protected override void Preprocess() * Group | CPU | Usage | User | Kernel | Idle */ - if (this.PreprocessedText.Contains("Group")) + /* + * DiskSpd v2.2.0 added Socket, Node, Core columns to the CPU table: + * + * Socket | Node | Group | Core | CPU | Usage | User | Kernel | Idle + * + * Normalize this to the existing Group | CPU format by: + * 1. Replacing the extended header so sectionizing produces a "CPU" section. + * 2. Stripping Socket, Node, Core from every data row. + */ + if (this.PreprocessedText.Contains("Socket | Node | Group | Core | CPU")) + { + this.PreprocessedText = this.PreprocessedText.Replace( + "Socket | Node | Group | Core | CPU", + $"CPU{Environment.NewLine}Group | CPU"); + + this.PreprocessedText = Regex.Replace( + this.PreprocessedText, + @"^\s*(\d+)\s*\|\s*(\d+)\s*\|\s*(\d+)\s*\|\s*(\d+)\s*\|\s*(\d+)\s*\|", + " $3| $5|", + RegexOptions.Multiline); + } + else if (this.PreprocessedText.Contains("Group")) { this.PreprocessedText = this.PreprocessedText.Replace("Group", $"CPU{Environment.NewLine}Group"); } diff --git a/src/VirtualClient/VirtualClient.Main/profiles/PERF-IO-DISKSPD.json b/src/VirtualClient/VirtualClient.Main/profiles/PERF-IO-DISKSPD.json index f1d940bbc7..67f2ac5672 100644 --- a/src/VirtualClient/VirtualClient.Main/profiles/PERF-IO-DISKSPD.json +++ b/src/VirtualClient/VirtualClient.Main/profiles/PERF-IO-DISKSPD.json @@ -382,7 +382,7 @@ "Parameters": { "Scenario": "InstallDiskSpdPackage", "BlobContainer": "packages", - "BlobName": "diskspd.2.0.21.zip", + "BlobName": "diskspd.2.2.0.zip", "PackageName": "diskspd", "Extract": true }