Skip to content

Commit

Permalink
Change DiskSpd Parser to skip parsing read on write-only and vise-ver…
Browse files Browse the repository at this point in the history
…sa (#410)

* Change DiskSpd Parser to skip parsing read on write-only and vise versa

* default enum

* test fix
  • Loading branch information
yangpanMS authored Dec 5, 2024
1 parent a464c15 commit 504ffb9
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 117 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.16.9
1.16.10
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System.IO;
using System.Reflection;
using NUnit.Framework;
using System.Collections.Generic;
using VirtualClient.Contracts;

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

namespace VirtualClient.Actions
{
Expand All @@ -17,7 +18,7 @@ public class DiskSpdMetricsParserTests
public void DiskSpdParserVerifyReadWrite()
{
string results = File.ReadAllText(MockFixture.GetDirectory(typeof(DiskSpdMetricsParserTests), "Examples", "DiskSpd", "DiskSpdExample-ReadWrite.txt"));
var parser = new DiskSpdMetricsParser(results);
var parser = new DiskSpdMetricsParser(results, "diskspd.exe -b8K -r8K -t32 -o16 -w50 -d900 -Suw -W50 -D -L -Rtext D:\\diskspd-test.dat");

IList<Metric> metrics = parser.Parse();

Expand Down Expand Up @@ -128,7 +129,7 @@ public void DiskSpdParserVerifyReadWrite()
public void DiskSpdParserVerifyWriteOnly()
{
string results = File.ReadAllText(MockFixture.GetDirectory(typeof(DiskSpdMetricsParserTests), "Examples", "DiskSpd", "DiskSpdExample-WriteOnly.txt"));
var parser = new DiskSpdMetricsParser(results);
var parser = new DiskSpdMetricsParser(results, "diskspd.exe -b8K -r8K -t32 -o16 -w100 -d900 -Suw -W30 -D -L -Rtext D:\\diskspd-test.dat");

IList<Metric> metrics = parser.Parse();

Expand All @@ -152,18 +153,6 @@ public void DiskSpdParserVerifyWriteOnly()
MetricAssert.Exists(metrics, "total iops total", 76458.71, "iops");
MetricAssert.Exists(metrics, "total latency average total", 6.696, "ms");

// Read
MetricAssert.Exists(metrics, "read bytes 0", 0, "bytes");
MetricAssert.Exists(metrics, "read bytes total", 0, "bytes");
MetricAssert.Exists(metrics, "read io operations 0", 0, "I/Os");
MetricAssert.Exists(metrics, "read io operations total", 0, "I/Os");
MetricAssert.Exists(metrics, "read throughput 0", 0, "MiB/s");
MetricAssert.Exists(metrics, "read throughput total", 0, "MiB/s");
MetricAssert.Exists(metrics, "read iops 0", 0, "iops");
MetricAssert.Exists(metrics, "read iops total", 0, "iops");
MetricAssert.Exists(metrics, "read latency average 0", 0, "ms");
MetricAssert.Exists(metrics, "read latency average total", 0, "ms");

// Write
MetricAssert.Exists(metrics, "write bytes 0", 23594541056, "bytes");
MetricAssert.Exists(metrics, "write io operations 0", 2880193, "I/Os");
Expand Down Expand Up @@ -213,8 +202,8 @@ public void DiskSpdParserVerifyWriteOnly()
[Test]
public void DiskSpdParserVerifyForCoreCountGreaterThan64WhichAddsProcessorGrouping()
{
string results = File.ReadAllText(MockFixture.GetDirectory(typeof(DiskSpdMetricsParserTests), "Examples", "DiskSpd", "Read8k.txt"));
var parser = new DiskSpdMetricsParser(results);
string results = File.ReadAllText(MockFixture.GetDirectory(typeof(DiskSpdMetricsParserTests), "Examples", "DiskSpd", "Write8k.txt"));
var parser = new DiskSpdMetricsParser(results, "diskspd.exe -b8K -r8K -t32 -o16 -w100 -d900 -Suw -W30 -D -L -Rtext D:\\diskspd-test.dat");

IList<Metric> metrics = parser.Parse();

Expand All @@ -236,11 +225,6 @@ public void DiskSpdParserVerifyForCoreCountGreaterThan64WhichAddsProcessorGroupi
MetricAssert.Exists(metrics, "total throughput 1", 36.17, "MiB/s");
MetricAssert.Exists(metrics, "total throughput total", 2579.05, "MiB/s");

// Read
MetricAssert.Exists(metrics, "read bytes 0", 0, "bytes");
MetricAssert.Exists(metrics, "read bytes 1", 0, "bytes");
MetricAssert.Exists(metrics, "read bytes total", 0, "bytes");

// Write
MetricAssert.Exists(metrics, "write bytes 0", 1927421952, "bytes");
MetricAssert.Exists(metrics, "write bytes 1", 2276425728, "bytes");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ private void CaptureMetrics(DiskWorkloadProcess workload, EventContext telemetry
this.MetadataContract.Apply(telemetryContext);

string result = workload.StandardOutput.ToString();
IList<Metric> metrics = new DiskSpdMetricsParser(result).Parse();
IList<Metric> metrics = new DiskSpdMetricsParser(result, this.CommandLine).Parse();

this.Logger.LogMetrics(
"DiskSpd",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,39 +32,29 @@ public class DiskSpdMetricsParser : MetricsParser
/// </summary>
private static readonly Regex DashLineRegex = new Regex(@"(-){2,}(\s)*", RegexOptions.ExplicitCapture);

private string commandLine;
private ReadWriteMode readWriteMode;
private List<Metric> metrics;

/// <summary>
/// Constructor for <see cref="DiskSpdMetricsParser"/>
/// </summary>
/// <param name="rawText">Raw text to parse.</param>
public DiskSpdMetricsParser(string rawText)
/// <param name="commandLine">DiskSpd commandline</param>
public DiskSpdMetricsParser(string rawText, string commandLine)
: base(rawText)
{
this.commandLine = commandLine;
this.metrics = new List<Metric>();
this.readWriteMode = ReadWriteMode.ReadWrite;
}

/// <summary>
/// Cpu usage.
/// </summary>
public DataTable CpuUsage { get; set; }

/// <summary>
/// Total IO result table
/// </summary>
public DataTable TotalIo { get; set; }

/// <summary>
/// Read IO result table
/// </summary>
public DataTable ReadIo { get; set; }

/// <summary>
/// Write IO result table
/// </summary>
public DataTable WriteIo { get; set; }

/// <summary>
/// Latency result table
/// </summary>
public DataTable Latency { get; set; }
private enum ReadWriteMode
{
ReadWrite,
ReadOnly,
WriteOnly,
}

/// <inheritdoc/>
public override IList<Metric> Parse()
Expand All @@ -76,38 +66,20 @@ public override IList<Metric> Parse()

this.ParseCPUResult();
this.ParseTotalIoResult();
this.ParseReadIoResult();
this.ParseWriteIoResult();

if (this.readWriteMode != ReadWriteMode.WriteOnly)
{
this.ParseReadIoResult();
}

if (this.readWriteMode != ReadWriteMode.ReadOnly)
{
this.ParseWriteIoResult();
}

this.ParseLatencyResult();

List<Metric> metrics = new List<Metric>();
metrics.AddRange(this.CpuUsage.GetMetrics(nameIndex: 0, valueIndex: 1, unit: "percentage", namePrefix: $"cpu {this.CpuUsage.Columns[1].ColumnName.ToLower()} ", metricRelativity: MetricRelativity.LowerIsBetter));
metrics.AddRange(this.CpuUsage.GetMetrics(nameIndex: 0, valueIndex: 2, unit: "percentage", namePrefix: $"cpu {this.CpuUsage.Columns[2].ColumnName.ToLower()} ", metricRelativity: MetricRelativity.LowerIsBetter));
metrics.AddRange(this.CpuUsage.GetMetrics(nameIndex: 0, valueIndex: 3, unit: "percentage", namePrefix: $"cpu {this.CpuUsage.Columns[3].ColumnName.ToLower()} ", metricRelativity: MetricRelativity.LowerIsBetter));

metrics.AddRange(this.TotalIo.GetMetrics(nameIndex: 0, valueIndex: 1, unit: "bytes", namePrefix: $"total {this.TotalIo.Columns[1].ColumnName} ", metricRelativity: MetricRelativity.HigherIsBetter));
metrics.AddRange(this.TotalIo.GetMetrics(nameIndex: 0, valueIndex: 2, unit: "I/Os", namePrefix: $"total {this.TotalIo.Columns[2].ColumnName} ", metricRelativity: MetricRelativity.HigherIsBetter));
metrics.AddRange(this.TotalIo.GetMetrics(nameIndex: 0, valueIndex: 3, unit: "MiB/s", namePrefix: $"total {this.TotalIo.Columns[3].ColumnName} ", metricRelativity: MetricRelativity.HigherIsBetter));
metrics.AddRange(this.TotalIo.GetMetrics(nameIndex: 0, valueIndex: 4, unit: "iops", namePrefix: $"total {this.TotalIo.Columns[4].ColumnName} ", metricRelativity: MetricRelativity.HigherIsBetter));
metrics.AddRange(this.TotalIo.GetMetrics(nameIndex: 0, valueIndex: 5, unit: "ms", namePrefix: $"total {this.TotalIo.Columns[5].ColumnName} ", metricRelativity: MetricRelativity.LowerIsBetter));

metrics.AddRange(this.ReadIo.GetMetrics(nameIndex: 0, valueIndex: 1, unit: "bytes", namePrefix: $"read {this.ReadIo.Columns[1].ColumnName} ", metricRelativity: MetricRelativity.HigherIsBetter));
metrics.AddRange(this.ReadIo.GetMetrics(nameIndex: 0, valueIndex: 2, unit: "I/Os", namePrefix: $"read {this.ReadIo.Columns[2].ColumnName} ", metricRelativity: MetricRelativity.HigherIsBetter));
metrics.AddRange(this.ReadIo.GetMetrics(nameIndex: 0, valueIndex: 3, unit: "MiB/s", namePrefix: $"read {this.ReadIo.Columns[3].ColumnName} ", metricRelativity: MetricRelativity.HigherIsBetter));
metrics.AddRange(this.ReadIo.GetMetrics(nameIndex: 0, valueIndex: 4, unit: "iops", namePrefix: $"read {this.ReadIo.Columns[4].ColumnName} ", metricRelativity: MetricRelativity.HigherIsBetter));
metrics.AddRange(this.ReadIo.GetMetrics(nameIndex: 0, valueIndex: 5, unit: "ms", namePrefix: $"read {this.ReadIo.Columns[5].ColumnName} ", metricRelativity: MetricRelativity.LowerIsBetter));

metrics.AddRange(this.WriteIo.GetMetrics(nameIndex: 0, valueIndex: 1, unit: "bytes", namePrefix: $"write {this.WriteIo.Columns[1].ColumnName} ", metricRelativity: MetricRelativity.HigherIsBetter));
metrics.AddRange(this.WriteIo.GetMetrics(nameIndex: 0, valueIndex: 2, unit: "I/Os", namePrefix: $"write {this.WriteIo.Columns[2].ColumnName} ", metricRelativity: MetricRelativity.HigherIsBetter));
metrics.AddRange(this.WriteIo.GetMetrics(nameIndex: 0, valueIndex: 3, unit: "MiB/s", namePrefix: $"write {this.WriteIo.Columns[3].ColumnName} ", metricRelativity: MetricRelativity.HigherIsBetter));
metrics.AddRange(this.WriteIo.GetMetrics(nameIndex: 0, valueIndex: 4, unit: "iops", namePrefix: $"write {this.WriteIo.Columns[4].ColumnName} ", metricRelativity: MetricRelativity.HigherIsBetter));
metrics.AddRange(this.WriteIo.GetMetrics(nameIndex: 0, valueIndex: 5, unit: "ms", namePrefix: $"write {this.WriteIo.Columns[5].ColumnName} ", metricRelativity: MetricRelativity.LowerIsBetter));

metrics.AddRange(this.Latency.GetMetrics(nameIndex: 0, valueIndex: 1, unit: "ms", namePrefix: "read latency ", metricRelativity: MetricRelativity.LowerIsBetter));
metrics.AddRange(this.Latency.GetMetrics(nameIndex: 0, valueIndex: 2, unit: "ms", namePrefix: "write latency ", metricRelativity: MetricRelativity.LowerIsBetter));
metrics.AddRange(this.Latency.GetMetrics(nameIndex: 0, valueIndex: 3, unit: "ms", namePrefix: "total latency ", metricRelativity: MetricRelativity.LowerIsBetter));

return metrics;
return this.metrics;
}
catch (Exception exc)
{
Expand Down Expand Up @@ -186,6 +158,15 @@ protected override void Preprocess()

// MiB/s -> throughput
this.PreprocessedText = this.PreprocessedText.Replace("MiB/s", "throughput");

if (this.commandLine.Contains("-w100"))
{
this.readWriteMode = ReadWriteMode.WriteOnly;
}
else if (this.commandLine.Contains("-w0"))
{
this.readWriteMode = ReadWriteMode.ReadOnly;
}
}

private void ParseCPUResult()
Expand All @@ -197,36 +178,62 @@ private void ParseCPUResult()
this.Sections[sectionName] = this.ProcessAndUpdateString(this.Sections[sectionName]);
}

this.CpuUsage = DataTableExtensions.ConvertToDataTable(
DataTable cpuUsage = DataTableExtensions.ConvertToDataTable(
this.Sections[sectionName], DiskSpdMetricsParser.DiskSpdDataTableDelimiter, sectionName, columnNames: null);

this.metrics.AddRange(cpuUsage.GetMetrics(nameIndex: 0, valueIndex: 1, unit: "percentage", namePrefix: $"cpu {cpuUsage.Columns[1].ColumnName.ToLower()} ", metricRelativity: MetricRelativity.LowerIsBetter));
this.metrics.AddRange(cpuUsage.GetMetrics(nameIndex: 0, valueIndex: 2, unit: "percentage", namePrefix: $"cpu {cpuUsage.Columns[2].ColumnName.ToLower()} ", metricRelativity: MetricRelativity.LowerIsBetter));
this.metrics.AddRange(cpuUsage.GetMetrics(nameIndex: 0, valueIndex: 3, unit: "percentage", namePrefix: $"cpu {cpuUsage.Columns[3].ColumnName.ToLower()} ", metricRelativity: MetricRelativity.LowerIsBetter));
}

private void ParseTotalIoResult()
{
string sectionName = "Total IO";
this.TotalIo = DataTableExtensions.ConvertToDataTable(
DataTable totalIo = DataTableExtensions.ConvertToDataTable(
this.Sections[sectionName], DiskSpdMetricsParser.DiskSpdDataTableDelimiter, sectionName, columnNames: null);

this.metrics.AddRange(totalIo.GetMetrics(nameIndex: 0, valueIndex: 1, unit: "bytes", namePrefix: $"total {totalIo.Columns[1].ColumnName} ", metricRelativity: MetricRelativity.HigherIsBetter));
this.metrics.AddRange(totalIo.GetMetrics(nameIndex: 0, valueIndex: 2, unit: "I/Os", namePrefix: $"total {totalIo.Columns[2].ColumnName} ", metricRelativity: MetricRelativity.HigherIsBetter));
this.metrics.AddRange(totalIo.GetMetrics(nameIndex: 0, valueIndex: 3, unit: "MiB/s", namePrefix: $"total {totalIo.Columns[3].ColumnName} ", metricRelativity: MetricRelativity.HigherIsBetter));
this.metrics.AddRange(totalIo.GetMetrics(nameIndex: 0, valueIndex: 4, unit: "iops", namePrefix: $"total {totalIo.Columns[4].ColumnName} ", metricRelativity: MetricRelativity.HigherIsBetter));
this.metrics.AddRange(totalIo.GetMetrics(nameIndex: 0, valueIndex: 5, unit: "ms", namePrefix: $"total {totalIo.Columns[5].ColumnName} ", metricRelativity: MetricRelativity.LowerIsBetter));
}

private void ParseReadIoResult()
{
string sectionName = "Read IO";
this.ReadIo = DataTableExtensions.ConvertToDataTable(
DataTable readIo = DataTableExtensions.ConvertToDataTable(
this.Sections[sectionName], DiskSpdMetricsParser.DiskSpdDataTableDelimiter, sectionName, columnNames: null);

this.metrics.AddRange(readIo.GetMetrics(nameIndex: 0, valueIndex: 1, unit: "bytes", namePrefix: $"read {readIo.Columns[1].ColumnName} ", metricRelativity: MetricRelativity.HigherIsBetter));
this.metrics.AddRange(readIo.GetMetrics(nameIndex: 0, valueIndex: 2, unit: "I/Os", namePrefix: $"read {readIo.Columns[2].ColumnName} ", metricRelativity: MetricRelativity.HigherIsBetter));
this.metrics.AddRange(readIo.GetMetrics(nameIndex: 0, valueIndex: 3, unit: "MiB/s", namePrefix: $"read {readIo.Columns[3].ColumnName} ", metricRelativity: MetricRelativity.HigherIsBetter));
this.metrics.AddRange(readIo.GetMetrics(nameIndex: 0, valueIndex: 4, unit: "iops", namePrefix: $"read {readIo.Columns[4].ColumnName} ", metricRelativity: MetricRelativity.HigherIsBetter));
this.metrics.AddRange(readIo.GetMetrics(nameIndex: 0, valueIndex: 5, unit: "ms", namePrefix: $"read {readIo.Columns[5].ColumnName} ", metricRelativity: MetricRelativity.LowerIsBetter));
}

private void ParseWriteIoResult()
{
string sectionName = "Write IO";
this.WriteIo = DataTableExtensions.ConvertToDataTable(
DataTable writeIo = DataTableExtensions.ConvertToDataTable(
this.Sections[sectionName], DiskSpdMetricsParser.DiskSpdDataTableDelimiter, sectionName, columnNames: null);

this.metrics.AddRange(writeIo.GetMetrics(nameIndex: 0, valueIndex: 1, unit: "bytes", namePrefix: $"write {writeIo.Columns[1].ColumnName} ", metricRelativity: MetricRelativity.HigherIsBetter));
this.metrics.AddRange(writeIo.GetMetrics(nameIndex: 0, valueIndex: 2, unit: "I/Os", namePrefix: $"write {writeIo.Columns[2].ColumnName} ", metricRelativity: MetricRelativity.HigherIsBetter));
this.metrics.AddRange(writeIo.GetMetrics(nameIndex: 0, valueIndex: 3, unit: "MiB/s", namePrefix: $"write {writeIo.Columns[3].ColumnName} ", metricRelativity: MetricRelativity.HigherIsBetter));
this.metrics.AddRange(writeIo.GetMetrics(nameIndex: 0, valueIndex: 4, unit: "iops", namePrefix: $"write {writeIo.Columns[4].ColumnName} ", metricRelativity: MetricRelativity.HigherIsBetter));
this.metrics.AddRange(writeIo.GetMetrics(nameIndex: 0, valueIndex: 5, unit: "ms", namePrefix: $"write {writeIo.Columns[5].ColumnName} ", metricRelativity: MetricRelativity.LowerIsBetter));
}

private void ParseLatencyResult()
{
string sectionName = "Latency";
this.Latency = DataTableExtensions.ConvertToDataTable(
DataTable latency = DataTableExtensions.ConvertToDataTable(
this.Sections[sectionName], DiskSpdMetricsParser.DiskSpdDataTableDelimiter, sectionName, columnNames: null);

this.metrics.AddRange(latency.GetMetrics(nameIndex: 0, valueIndex: 1, unit: "ms", namePrefix: "read latency ", metricRelativity: MetricRelativity.LowerIsBetter));
this.metrics.AddRange(latency.GetMetrics(nameIndex: 0, valueIndex: 2, unit: "ms", namePrefix: "write latency ", metricRelativity: MetricRelativity.LowerIsBetter));
this.metrics.AddRange(latency.GetMetrics(nameIndex: 0, valueIndex: 3, unit: "ms", namePrefix: "total latency ", metricRelativity: MetricRelativity.LowerIsBetter));
}

private string ProcessAndUpdateString(string input)
Expand Down

This file was deleted.

0 comments on commit 504ffb9

Please sign in to comment.