Skip to content

Instantly share code, notes, and snippets.

@stonstad
Last active April 22, 2024 15:03
Show Gist options
  • Save stonstad/43e027ecc580612c5abd5e1fcf1e30d8 to your computer and use it in GitHub Desktop.
Save stonstad/43e027ecc580612c5abd5e1fcf1e30d8 to your computer and use it in GitHub Desktop.
BenchmarkDotNet Metadata Column
BenchmarkDotNet Metadata Column
- Stores benchmark metadata to the file system for subsequent retrieval by a custom column.
- Do not use for storing benchmark measurements.
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Reports;
using BenchmarkDotNet.Running;
using System.Linq;
namespace Example.Benchmarking
{
public class BenchmarkCustomColumn : IColumn
{
public string Id => nameof(BenchmarkCustomColumn);
public string ColumnName { get; private set; }
public bool AlwaysShow => true;
public ColumnCategory Category => ColumnCategory.Custom;
public int PriorityInCategory => 1;
public bool IsNumeric => true;
public UnitType UnitType { get; private set; }
public string Legend => "Custom Column";
public bool IsAvailable(Summary summary) => true;
public bool IsDefault(Summary summary, BenchmarkCase benchmarkCase) => true;
public BenchmarkCustomColumn(string columnName, UnitType unitType)
{
ColumnName = columnName;
UnitType = unitType;
}
public string GetValue(Summary summary, BenchmarkCase benchmarkCase)
{
string benchmarkName = benchmarkCase.Descriptor.WorkloadMethod.Name;
BenchmarkMetadata.Instance.Load($"{benchmarkName}");
var metadata = BenchmarkMetadata.Instance.GetMetdata(ColumnName);
if (metadata.Count > 0)
{
object value = metadata.Values.LastOrDefault();
if (value != null)
return value.ToString();
else
return "N/A";
}
else
return "N/A";
}
public string GetValue(Summary summary, BenchmarkCase benchmarkCase, SummaryStyle style)
{
return GetValue(summary, benchmarkCase);
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
namespace Example.Benchmarking
{
public class BenchmarkMetadata
{
public static BenchmarkMetadata Instance { get; } = new BenchmarkMetadata();
private Dictionary<string, SortedList<int, object>> _Metadata = new Dictionary<string, SortedList<int, object>>();
private string _DocumentsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
private const string _BenchmarkDirectoryName = "Custom Benchmark Data";
private int _Index = 0;
public void Load(string benchmarkName)
{
// directory
string directory = Path.Combine(_DocumentsPath, _BenchmarkDirectoryName);
if (!Directory.Exists(directory))
Directory.CreateDirectory(directory);
// file
string fileName = Path.Combine(directory, $"{benchmarkName}.json");
if (File.Exists(fileName))
{
string json = File.ReadAllText(fileName);
_Metadata = JsonSerializer.Deserialize<Dictionary<string, SortedList<int, object>>> (json);
}
}
public void Save(string benchmarkName)
{
// directory
string directory = Path.Combine(_DocumentsPath, _BenchmarkDirectoryName);
if (!Directory.Exists(directory))
Directory.CreateDirectory(directory);
// file
string fileName = Path.Combine(directory, $"{benchmarkName}.json");
string json = JsonSerializer.Serialize(_Metadata);
File.WriteAllText(fileName, json);
}
public void AddMetadata(string name, object value)
{
if (!_Metadata.ContainsKey(name))
_Metadata[name] = new SortedList<int, object>();
_Metadata[name].Add(_Index++, value);
}
public SortedList<int, object> GetMetdata(string name)
{
if (_Metadata.TryGetValue(name, out SortedList<int, object> values))
return values;
return null;
}
}
}
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Loggers;
namespace Example.Benchmarking
{
public class BenchmarkConfiguration : ManualConfig
{
public BenchmarkConfiguration()
{
AddJob(Job.Default);
AddLogger(ConsoleLogger.Default);
AddColumn(TargetMethodColumn.Method);
AddColumn(new BenchmarkCustomColumn("YourColumnName", UnitType.Size)); // Your custom column
}
}
}
using BenchmarkDotNet.Attributes;
using System;
using System.Collections.Generic;
using System.IO;
namespace Example.Benchmarking
{
public class ExampleBenchmark
{
private string _BenchmarkName = null;
[IterationSetup(Target = nameof(ExampleBenchmark))]
public void IterationSetupExampleBenchmark()
{
_BenchmarkName = nameof(ExampleBenchmark);
}
[IterationCleanup]
public void IterationCleanup()
{
BenchmarkMetadata.Instance.AddMetadata("YourColumnName", "Hello"); // add benchmark metadata
BenchmarkMetadata.Instance.Save(_BenchmarkName);
}
[Benchmark]
public void ExampleBenchmark()
{
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment