Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Lat_Rd_Mem support in LMBENCH #420

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"stride=64
0.00049 1.438
0.00098 1.438
0.00195 1.438
0.00293 1.438
0.00391 1.438
0.00781 1.438
0.01172 1.438
0.01562 1.438
0.03125 1.439
0.04688 1.915
0.06250 1.938
0.12500 1.991
0.18750 1.890
0.25000 1.839
0.50000 1.766
0.75000 1.740
1.00000 1.757
2.00000 3.069
3.00000 3.106
4.00000 3.093
8.00000 3.084
12.00000 3.081
16.00000 3.084
32.00000 3.090
48.00000 3.820
64.00000 4.545
128.00000 5.335

"stride=32
0.00049 1.438
0.00098 1.438
0.00195 1.438
0.00293 1.438
0.00391 1.438
0.00781 1.438
0.01172 1.438
0.01562 1.438
0.03125 1.438
0.04688 1.439
0.06250 1.563
0.12500 1.532
0.18750 1.521
0.25000 1.516
0.50000 1.508
0.75000 1.506
1.00000 1.506
2.00000 1.588
3.00000 1.588
4.00000 1.587
8.00000 1.586
12.00000 1.586
16.00000 1.586
32.00000 1.612
48.00000 1.831
64.00000 2.056
128.00000 2.537
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

namespace VirtualClient.Actions
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using NUnit.Framework;
using VirtualClient.Contracts;

[TestFixture]
[Category("Unit")]
public class LatMemRdMetricsParserTests
{
private static string Examples = MockFixture.GetDirectory(typeof(LMbenchExecutorTests), "Examples", "LMbench");
private MockFixture mockFixture;

[SetUp]
public void SetupTest()
{
this.mockFixture = new MockFixture();
this.mockFixture.Setup(PlatformID.Unix);
}

[Test]
public void LMbenchMetricsParserCapturesTheExpectedMetrics_1()
{
string workingDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string outputPath = this.mockFixture.Combine(LatMemRdMetricsParserTests.Examples, "latmemrd_example_results.txt");
string results = File.ReadAllText(outputPath);

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

Assert.IsTrue(metrics.Count == 54);
Assert.IsNotNull(metrics.FirstOrDefault(m => m.Name == "Latency_StrideBytes_64_Array_512_B" && m.Value == 1.438));
Assert.IsNotNull(metrics.FirstOrDefault(m => m.Name == "Latency_StrideBytes_64_Array_1_KiB" && m.Value == 1.438));
Assert.IsNotNull(metrics.FirstOrDefault(m => m.Name == "Latency_StrideBytes_32_Array_768_KiB" && m.Value == 1.506));
Assert.IsNotNull(metrics.FirstOrDefault(m => m.Name == "Latency_StrideBytes_32_Array_32_MiB" && m.Value == 1.612));
}
}
}
70 changes: 64 additions & 6 deletions src/VirtualClient/VirtualClient.Actions/LMbench/LMbenchExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ namespace VirtualClient.Actions
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO.Abstractions;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.Extensions.DependencyInjection;
using VirtualClient.Common;
using VirtualClient.Common.Extensions;
Expand Down Expand Up @@ -84,6 +86,28 @@ public IEnumerable<string> Benchmarks
}
}

/// <summary>
/// Name of the Binary to run for the suite of Benchmarks compiled.
/// </summary>
public string BinaryName
{
get
{
return this.Parameters.GetValue<string>(nameof(this.BinaryName), null);
}
}

/// <summary>
/// Name of the Binary to run for the suite of Benchmarks compiled.
/// </summary>
public string BinaryCommandLine
{
get
{
return this.Parameters.GetValue<string>(nameof(this.BinaryCommandLine), null);
}
}

/// <summary>
/// The compilerFlags that are used for make command in compiling LMbench.
/// </summary>
Expand Down Expand Up @@ -119,7 +143,41 @@ public long? MemorySizeMB
protected override async Task ExecuteAsync(EventContext telemetryContext, CancellationToken cancellationToken)
{
await this.BuildSourceCodeAsync(telemetryContext, cancellationToken);
await this.ExecuteWorkloadAsync(telemetryContext, cancellationToken);
if (this.BinaryName == null)
{
await this.ExecuteWorkloadAsync(telemetryContext, cancellationToken);
}
else if (this.BinaryName.Equals("lat_mem_rd", StringComparison.OrdinalIgnoreCase))
{
string binaryPath = string.Empty;
if (this.Platform == PlatformID.Unix && this.CpuArchitecture == Architecture.X64)
{
binaryPath = this.PlatformSpecifics.Combine(this.LMbenchPackage.Path, "bin", "x86_64-Linux");
}
else if (this.Platform == PlatformID.Unix && this.CpuArchitecture == Architecture.Arm64)
{
binaryPath = this.PlatformSpecifics.Combine(this.LMbenchPackage.Path, "bin", "aarch64-Linux");
}
else
{
this.Logger.LogNotSupported(this.BinaryName, this.Platform, this.CpuArchitecture, EventContext.Persisted());
}

if (!string.IsNullOrEmpty(binaryPath))
{
using (IProcessProxy executeBinary = await this.ExecuteCommandAsync(this.PlatformSpecifics.Combine(binaryPath, this.BinaryName), this.BinaryCommandLine, binaryPath, telemetryContext, cancellationToken))
{
await this.LogProcessDetailsAsync(executeBinary, telemetryContext);
executeBinary.ThrowIfErrored<WorkloadException>(ProcessProxy.DefaultSuccessCodes, errorReason: ErrorReason.WorkloadFailed);
LatMemRdMetricsParser latMemRdMetricsParser = new LatMemRdMetricsParser($"{executeBinary.StandardOutput.ToString()}{executeBinary.StandardError.ToString()}");
this.CaptureMetrics(executeBinary, latMemRdMetricsParser, telemetryContext, this.BinaryName);
}
}
}
else
{
this.Logger.LogMessage($"Unsupported {nameof(this.BinaryName)}: {this.BinaryName}, supported binarienames are : null(for sumarry),lat_rd_mem", telemetryContext);
}
}

/// <summary>
Expand Down Expand Up @@ -180,7 +238,7 @@ private Task BuildSourceCodeAsync(EventContext telemetryContext, CancellationTok
});
}

private void CaptureMetrics(IProcessProxy process, EventContext telemetryContext)
private void CaptureMetrics(IProcessProxy process, MetricsParser metricsParser, EventContext telemetryContext, string scenario)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

telemetryContext at last parameter

{
this.MetadataContract.AddForScenario(
"LMbench",
Expand All @@ -189,12 +247,11 @@ private void CaptureMetrics(IProcessProxy process, EventContext telemetryContext

this.MetadataContract.Apply(telemetryContext);

LMbenchMetricsParser parser = new LMbenchMetricsParser(process.StandardOutput.ToString());
IList<Metric> metrics = parser.Parse();
IList<Metric> metrics = metricsParser.Parse();

this.Logger.LogMetrics(
toolName: "LMbench",
scenarioName: "Memory Benchmark",
scenarioName: scenario,
process.StartTime,
process.ExitTime,
metrics,
Expand Down Expand Up @@ -268,7 +325,8 @@ private Task ExecuteWorkloadAsync(EventContext telemetryContext, CancellationTok

// The use of the original telemetry context created at the top
// is purposeful.
this.CaptureMetrics(process, relatedContext);
LMbenchMetricsParser lmbenchMetricsParser = new LMbenchMetricsParser(process.StandardOutput.ToString());
this.CaptureMetrics(process, lmbenchMetricsParser, relatedContext, "Memory Benchmark");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:Avoid spaces as much as we could, use an underscore

}
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using VirtualClient.Contracts;

namespace VirtualClient.Actions
{
/// <summary>
///
/// </summary>
public class LatMemRdMetricsParser : MetricsParser
{
/// <summary>
/// Sectionize by one or more empty lines.
/// </summary>
private static readonly Regex LatMemRdSectionDelimiter = new Regex(@$"({Environment.NewLine})(\s)*({Environment.NewLine})", RegexOptions.ExplicitCapture);

/// <summary>
/// Initializes a new instance of the <see cref="LatMemRdMetricsParser"/> class.
/// </summary>
/// <param name="rawText"></param>
public LatMemRdMetricsParser(string rawText)
: base(rawText)
{
}

/// <inheritdoc/>
public override IList<Metric> Parse()
{
IList<Metric> metrics = new List<Metric>();
this.Preprocess();
this.Sections = TextParsingExtensions.Sectionize(this.PreprocessedText, LatMemRdSectionDelimiter);
foreach (var section in this.Sections)
{
var lines = section.Value.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
{
var values = line.Split(' ');
string strideSize = section.Key.Split('=')[1];
var metadata = new Dictionary<string, IConvertible>();
metadata.Add("StrideSizeBytes", strideSize);
metadata.Add("ArraySizeInMiB", values[0]);
long arraySizeInBytes = this.RoundOffToNearest512Multiple(double.Parse(values[0]) * 1024 * 1024) * 512;
metrics.Add(new Metric($"Latency_StrideBytes_{strideSize}_Array_{this.MetricNameSuffix(arraySizeInBytes)}", double.Parse(values[1]), "ns", MetricRelativity.LowerIsBetter, null, $"Latency for memory read operation for Array size in MB {values[0]} & stride size {strideSize} in nano seconds", metadata));
}
}

return metrics;

}

/// <inheritdoc/>
protected override void Preprocess()
{
// Removing unnecessary starting and ending space.
this.PreprocessedText = this.RawText.Trim();
}

private long RoundOffToNearest512Multiple(double number)
{
return (long)Math.Round(number / 512.0);
}

private string MetricNameSuffix(double bytes)
{
if (bytes >= 1024 * 1024)
{
return $"{bytes / (1024 * 1024)}_MiB";
}
else if (bytes >= 1024)
{
return $"{bytes / 1024}_KiB";
}
else
{
return $"{bytes}_B";
}

}
}
}
Loading