From b9c2aca8d3f5ebc339c94492a7a2c107aa23e7e2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 5 Jan 2026 09:33:50 +0000 Subject: [PATCH 1/2] Initial plan From 3d8308113f433d41d8fc3d1542af67aa86eb1012 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 5 Jan 2026 09:47:45 +0000 Subject: [PATCH 2/2] Convert HardwareCounter from enum to static class with const strings Co-authored-by: ramartinez7 <44536177+ramartinez7@users.noreply.github.com> --- .../EtwProfilerConfig.cs | 6 +- .../HardwareCounters.cs | 6 +- .../Attributes/HardwareCountersAttribute.cs | 2 +- .../CharacteristicSetPresenter.cs | 2 +- .../Configs/ConfigExtensions.cs | 2 +- src/BenchmarkDotNet/Configs/DebugConfig.cs | 2 +- src/BenchmarkDotNet/Configs/DefaultConfig.cs | 2 +- src/BenchmarkDotNet/Configs/IConfig.cs | 2 +- .../Configs/ImmutableConfig.cs | 6 +- .../Configs/ImmutableConfigBuilder.cs | 2 +- src/BenchmarkDotNet/Configs/ManualConfig.cs | 6 +- .../ConsoleArguments/ConfigParser.cs | 8 +- .../Diagnosers/HardwareCounter.cs | 112 +++++++++++------- src/BenchmarkDotNet/Diagnosers/PmcStats.cs | 6 +- .../Diagnosers/PreciseMachineCounter.cs | 10 +- .../Exporters/InstructionPointerExporter.cs | 10 +- 16 files changed, 103 insertions(+), 81 deletions(-) diff --git a/src/BenchmarkDotNet.Diagnostics.Windows/EtwProfilerConfig.cs b/src/BenchmarkDotNet.Diagnostics.Windows/EtwProfilerConfig.cs index 7846edd1dd..0a57e79e47 100644 --- a/src/BenchmarkDotNet.Diagnostics.Windows/EtwProfilerConfig.cs +++ b/src/BenchmarkDotNet.Diagnostics.Windows/EtwProfilerConfig.cs @@ -21,7 +21,7 @@ public class EtwProfilerConfig public KernelTraceEventParser.Keywords KernelStackKeywords { get; } - public IReadOnlyDictionary> IntervalSelectors { get; } + public IReadOnlyDictionary> IntervalSelectors { get; } public IReadOnlyCollection<(Guid providerGuid, TraceEventLevel providerLevel, ulong keywords, TraceEventProviderOptions options)> Providers { get; } @@ -41,7 +41,7 @@ public EtwProfilerConfig( float cpuSampleIntervalInMilliseconds = 1.0f, KernelTraceEventParser.Keywords kernelKeywords = KernelTraceEventParser.Keywords.ImageLoad | KernelTraceEventParser.Keywords.Profile, KernelTraceEventParser.Keywords kernelStackKeywords = KernelTraceEventParser.Keywords.Profile, - IReadOnlyDictionary>? intervalSelectors = null, + IReadOnlyDictionary>? intervalSelectors = null, IReadOnlyCollection<(Guid providerGuid, TraceEventLevel providerLevel, ulong keywords, TraceEventProviderOptions options)>? providers = null, bool createHeapSession = false) { @@ -51,7 +51,7 @@ public EtwProfilerConfig( PerformExtraBenchmarksRun = performExtraBenchmarksRun; BufferSizeInMb = bufferSizeInMb; CpuSampleIntervalInMilliseconds = cpuSampleIntervalInMilliseconds; - IntervalSelectors = intervalSelectors ?? new Dictionary> + IntervalSelectors = intervalSelectors ?? new Dictionary> { // following values come from xunit-performance, were selected based on a many trace files from benchmark runs // to keep good balance between accuracy and trace file size diff --git a/src/BenchmarkDotNet.Diagnostics.Windows/HardwareCounters.cs b/src/BenchmarkDotNet.Diagnostics.Windows/HardwareCounters.cs index e1ae47a843..9def3f7eb2 100644 --- a/src/BenchmarkDotNet.Diagnostics.Windows/HardwareCounters.cs +++ b/src/BenchmarkDotNet.Diagnostics.Windows/HardwareCounters.cs @@ -12,8 +12,8 @@ namespace BenchmarkDotNet.Diagnostics.Windows { public static class HardwareCounters { - private static readonly Dictionary EtwTranslations - = new Dictionary + private static readonly Dictionary EtwTranslations + = new Dictionary { { HardwareCounter.Timer, "Timer" }, { HardwareCounter.TotalIssues, "TotalIssues" }, @@ -88,7 +88,7 @@ public static IEnumerable Validate(ValidationParameters validat } } - internal static PreciseMachineCounter FromCounter(HardwareCounter counter, Func intervalSelector) + internal static PreciseMachineCounter FromCounter(string counter, Func intervalSelector) { var profileSource = TraceEventProfileSources.GetInfo()[EtwTranslations[counter]]; // it can't fail, diagnoser validates that first diff --git a/src/BenchmarkDotNet/Attributes/HardwareCountersAttribute.cs b/src/BenchmarkDotNet/Attributes/HardwareCountersAttribute.cs index aa8168aafb..1dc40395e9 100644 --- a/src/BenchmarkDotNet/Attributes/HardwareCountersAttribute.cs +++ b/src/BenchmarkDotNet/Attributes/HardwareCountersAttribute.cs @@ -15,7 +15,7 @@ protected HardwareCountersAttribute() Config = ManualConfig.CreateEmpty(); } - public HardwareCountersAttribute(params HardwareCounter[] counters) + public HardwareCountersAttribute(params string[] counters) { Config = ManualConfig.CreateEmpty().AddHardwareCounters(counters); } diff --git a/src/BenchmarkDotNet/Characteristics/CharacteristicSetPresenter.cs b/src/BenchmarkDotNet/Characteristics/CharacteristicSetPresenter.cs index ffaa5dba6c..110ca5ad1b 100644 --- a/src/BenchmarkDotNet/Characteristics/CharacteristicSetPresenter.cs +++ b/src/BenchmarkDotNet/Characteristics/CharacteristicSetPresenter.cs @@ -70,7 +70,7 @@ private class SourceCodePresenter : CharacteristicSetPresenter private static readonly HashSet NonExportableTypes = new HashSet { typeof(IToolchain), // there is no need to set toolchain in child process, it was causing parameterless ctor requirement for all IToolchain implementations - typeof(IReadOnlyCollection), // we don't need to export this array to child process + typeof(IReadOnlyCollection), // we don't need to export this array to child process typeof(IReadOnlyList), typeof(IReadOnlyList), typeof(Runtime) // there is no need to set runtime in child process, it was causing parameterless ctor requirement for all Runtime implementations diff --git a/src/BenchmarkDotNet/Configs/ConfigExtensions.cs b/src/BenchmarkDotNet/Configs/ConfigExtensions.cs index 3159dd692f..c132c767e0 100644 --- a/src/BenchmarkDotNet/Configs/ConfigExtensions.cs +++ b/src/BenchmarkDotNet/Configs/ConfigExtensions.cs @@ -39,7 +39,7 @@ public static class ConfigExtensions [PublicAPI] public static ManualConfig WithOrderer(this IConfig config, IOrderer orderer) => config.With(m => m.WithOrderer(orderer)); - [PublicAPI] public static ManualConfig AddHardwareCounters(this IConfig config, params HardwareCounter[] counters) => config.With(c => c.AddHardwareCounters(counters)); + [PublicAPI] public static ManualConfig AddHardwareCounters(this IConfig config, params string[] counters) => config.With(c => c.AddHardwareCounters(counters)); [PublicAPI] public static ManualConfig AddFilter(this IConfig config, params IFilter[] filters) => config.With(c => c.AddFilter(filters)); diff --git a/src/BenchmarkDotNet/Configs/DebugConfig.cs b/src/BenchmarkDotNet/Configs/DebugConfig.cs index 3a19067388..cf64d08a88 100644 --- a/src/BenchmarkDotNet/Configs/DebugConfig.cs +++ b/src/BenchmarkDotNet/Configs/DebugConfig.cs @@ -56,7 +56,7 @@ public abstract class DebugConfig : IConfig public IEnumerable GetLoggers() => [ConsoleLogger.Default]; public IEnumerable GetDiagnosers() => []; public IEnumerable GetAnalysers() => []; - public IEnumerable GetHardwareCounters() => []; + public IEnumerable GetHardwareCounters() => []; public IEnumerable GetCustomCounters() => []; public IEnumerable GetEventProcessors() => []; public IEnumerable GetFilters() => []; diff --git a/src/BenchmarkDotNet/Configs/DefaultConfig.cs b/src/BenchmarkDotNet/Configs/DefaultConfig.cs index 33a2b7b3df..de973e294d 100644 --- a/src/BenchmarkDotNet/Configs/DefaultConfig.cs +++ b/src/BenchmarkDotNet/Configs/DefaultConfig.cs @@ -117,7 +117,7 @@ public string ArtifactsPath public IEnumerable GetDiagnosers() => Array.Empty(); - public IEnumerable GetHardwareCounters() => Array.Empty(); + public IEnumerable GetHardwareCounters() => Array.Empty(); public IEnumerable GetCustomCounters() => Array.Empty(); diff --git a/src/BenchmarkDotNet/Configs/IConfig.cs b/src/BenchmarkDotNet/Configs/IConfig.cs index 09b7e00fcf..635191455c 100644 --- a/src/BenchmarkDotNet/Configs/IConfig.cs +++ b/src/BenchmarkDotNet/Configs/IConfig.cs @@ -25,7 +25,7 @@ public interface IConfig IEnumerable GetAnalysers(); IEnumerable GetJobs(); IEnumerable GetValidators(); - IEnumerable GetHardwareCounters(); + IEnumerable GetHardwareCounters(); IEnumerable GetCustomCounters(); IEnumerable GetFilters(); IEnumerable GetLogicalGroupRules(); diff --git a/src/BenchmarkDotNet/Configs/ImmutableConfig.cs b/src/BenchmarkDotNet/Configs/ImmutableConfig.cs index caa98a700d..f185f2ec7b 100644 --- a/src/BenchmarkDotNet/Configs/ImmutableConfig.cs +++ b/src/BenchmarkDotNet/Configs/ImmutableConfig.cs @@ -29,7 +29,7 @@ public sealed class ImmutableConfig : IConfig private readonly ImmutableHashSet analysers; private readonly ImmutableHashSet validators; private readonly ImmutableHashSet jobs; - private readonly ImmutableHashSet hardwareCounters; + private readonly ImmutableHashSet hardwareCounters; private readonly ImmutableHashSet customCounters; private readonly ImmutableHashSet filters; private readonly ImmutableArray rules; @@ -39,7 +39,7 @@ public sealed class ImmutableConfig : IConfig internal ImmutableConfig( ImmutableArray uniqueColumnProviders, ImmutableHashSet uniqueLoggers, - ImmutableHashSet uniqueHardwareCounters, + ImmutableHashSet uniqueHardwareCounters, ImmutableHashSet uniqueCustomCounters, ImmutableHashSet uniqueDiagnosers, ImmutableArray uniqueExporters, @@ -103,7 +103,7 @@ internal ImmutableConfig( public IEnumerable GetAnalysers() => analysers; public IEnumerable GetJobs() => jobs; public IEnumerable GetValidators() => validators; - public IEnumerable GetHardwareCounters() => hardwareCounters; + public IEnumerable GetHardwareCounters() => hardwareCounters; public IEnumerable GetCustomCounters() => customCounters; public IEnumerable GetFilters() => filters; public IEnumerable GetLogicalGroupRules() => rules; diff --git a/src/BenchmarkDotNet/Configs/ImmutableConfigBuilder.cs b/src/BenchmarkDotNet/Configs/ImmutableConfigBuilder.cs index 0fcd588800..c226a2752e 100644 --- a/src/BenchmarkDotNet/Configs/ImmutableConfigBuilder.cs +++ b/src/BenchmarkDotNet/Configs/ImmutableConfigBuilder.cs @@ -83,7 +83,7 @@ public static ImmutableConfig Create(IConfig source) ); } - private static ImmutableHashSet GetDiagnosers(IEnumerable diagnosers, ImmutableHashSet uniqueHardwareCounters, ImmutableHashSet uniqueCustomCounters) + private static ImmutableHashSet GetDiagnosers(IEnumerable diagnosers, ImmutableHashSet uniqueHardwareCounters, ImmutableHashSet uniqueCustomCounters) { var builder = ImmutableHashSet.CreateBuilder(new TypeComparer()); diff --git a/src/BenchmarkDotNet/Configs/ManualConfig.cs b/src/BenchmarkDotNet/Configs/ManualConfig.cs index 7f88b8144c..650874a3c1 100644 --- a/src/BenchmarkDotNet/Configs/ManualConfig.cs +++ b/src/BenchmarkDotNet/Configs/ManualConfig.cs @@ -31,7 +31,7 @@ public class ManualConfig : IConfig private readonly List analysers = new List(); private readonly List validators = new List(); private readonly List jobs = new List(); - private readonly HashSet hardwareCounters = new HashSet(); + private readonly HashSet hardwareCounters = new HashSet(); private readonly HashSet customCounters = new HashSet(); private readonly List filters = new List(); private readonly List logicalGroupRules = new List(); @@ -45,7 +45,7 @@ public class ManualConfig : IConfig public IEnumerable GetAnalysers() => analysers; public IEnumerable GetValidators() => validators; public IEnumerable GetJobs() => jobs; - public IEnumerable GetHardwareCounters() => hardwareCounters; + public IEnumerable GetHardwareCounters() => hardwareCounters; public IEnumerable GetCustomCounters() => customCounters; public IEnumerable GetFilters() => filters; public IEnumerable GetLogicalGroupRules() => logicalGroupRules; @@ -166,7 +166,7 @@ public ManualConfig AddJob(params Job[] newJobs) return this; } - public ManualConfig AddHardwareCounters(params HardwareCounter[] newHardwareCounters) + public ManualConfig AddHardwareCounters(params string[] newHardwareCounters) { hardwareCounters.AddRange(newHardwareCounters); return this; diff --git a/src/BenchmarkDotNet/ConsoleArguments/ConfigParser.cs b/src/BenchmarkDotNet/ConsoleArguments/ConfigParser.cs index 58b1736411..a97f56b768 100644 --- a/src/BenchmarkDotNet/ConsoleArguments/ConfigParser.cs +++ b/src/BenchmarkDotNet/ConsoleArguments/ConfigParser.cs @@ -304,11 +304,13 @@ private static bool Validate(CommandLineOptions options, ILogger logger) } foreach (var counterName in options.HardwareCounters) - if (!Enum.TryParse(counterName, ignoreCase: true, out HardwareCounter _)) + { + if (!HardwareCounter.All.Contains(counterName, System.StringComparer.OrdinalIgnoreCase)) { - logger.WriteLineError($"The provided hardware counter \"{counterName}\" is invalid. Available options are: {string.Join("+", Enum.GetNames(typeof(HardwareCounter)))}."); + logger.WriteLineError($"The provided hardware counter \"{counterName}\" is invalid. Available options are: {string.Join("+", HardwareCounter.All)}."); return false; } + } if (options.StatisticalTestThreshold.IsNotBlank() && !Threshold.TryParse(options.StatisticalTestThreshold, out _)) { @@ -340,7 +342,7 @@ private static IConfig CreateConfig(CommandLineOptions options, IConfig? globalC config.AddExporter(options.Exporters.SelectMany(exporter => AvailableExporters[exporter]).ToArray()); config.AddHardwareCounters(options.HardwareCounters - .Select(counterName => (HardwareCounter)Enum.Parse(typeof(HardwareCounter), counterName, ignoreCase: true)) + .Select(counterName => HardwareCounter.All.FirstOrDefault(c => c.Equals(counterName, System.StringComparison.OrdinalIgnoreCase)) ?? counterName) .ToArray()); if (options.UseMemoryDiagnoser) diff --git a/src/BenchmarkDotNet/Diagnosers/HardwareCounter.cs b/src/BenchmarkDotNet/Diagnosers/HardwareCounter.cs index 9b72a5a775..260333dac4 100644 --- a/src/BenchmarkDotNet/Diagnosers/HardwareCounter.cs +++ b/src/BenchmarkDotNet/Diagnosers/HardwareCounter.cs @@ -1,84 +1,104 @@ using System; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using JetBrains.Annotations; namespace BenchmarkDotNet.Diagnosers { // initial list is based on counters available for Windows, run `tracelog.exe -profilesources Help` to get the list [SuppressMessage("ReSharper", "IdentifierTypo")] - public enum HardwareCounter + [PublicAPI] + public static class HardwareCounter { - NotSet = 0, - Timer, - TotalIssues, - BranchInstructions, - CacheMisses, - BranchMispredictions, - TotalCycles, - UnhaltedCoreCycles, - InstructionRetired, - UnhaltedReferenceCycles, - LlcReference, - LlcMisses, - BranchInstructionRetired, - BranchMispredictsRetired - } + public const string NotSet = nameof(NotSet); + public const string Timer = nameof(Timer); + public const string TotalIssues = nameof(TotalIssues); + public const string BranchInstructions = nameof(BranchInstructions); + public const string CacheMisses = nameof(CacheMisses); + public const string BranchMispredictions = nameof(BranchMispredictions); + public const string TotalCycles = nameof(TotalCycles); + public const string UnhaltedCoreCycles = nameof(UnhaltedCoreCycles); + public const string InstructionRetired = nameof(InstructionRetired); + public const string UnhaltedReferenceCycles = nameof(UnhaltedReferenceCycles); + public const string LlcReference = nameof(LlcReference); + public const string LlcMisses = nameof(LlcMisses); + public const string BranchInstructionRetired = nameof(BranchInstructionRetired); + public const string BranchMispredictsRetired = nameof(BranchMispredictsRetired); + + /// + /// Gets all available hardware counter names. + /// + public static IReadOnlyList All { get; } = new[] + { + Timer, + TotalIssues, + BranchInstructions, + CacheMisses, + BranchMispredictions, + TotalCycles, + UnhaltedCoreCycles, + InstructionRetired, + UnhaltedReferenceCycles, + LlcReference, + LlcMisses, + BranchInstructionRetired, + BranchMispredictsRetired + }; - public static class HardwareCounterExtensions - { [SuppressMessage("ReSharper", "StringLiteralTypo")] - public static string ToShortName(this HardwareCounter hardwareCounter) + public static string ToShortName(string hardwareCounter) { switch (hardwareCounter) { - case HardwareCounter.Timer: + case Timer: return "timer"; - case HardwareCounter.TotalIssues: + case TotalIssues: return "issues"; - case HardwareCounter.BranchInstructions: + case BranchInstructions: return "branch"; - case HardwareCounter.CacheMisses: + case CacheMisses: return "miss"; - case HardwareCounter.BranchMispredictions: + case BranchMispredictions: return "mispred"; - case HardwareCounter.TotalCycles: + case TotalCycles: return "cycles"; - case HardwareCounter.UnhaltedCoreCycles: + case UnhaltedCoreCycles: return "unCoreCycles"; - case HardwareCounter.InstructionRetired: + case InstructionRetired: return "retired"; - case HardwareCounter.UnhaltedReferenceCycles: + case UnhaltedReferenceCycles: return "unRefCycles"; - case HardwareCounter.LlcReference: + case LlcReference: return "llcRef"; - case HardwareCounter.LlcMisses: + case LlcMisses: return "llcMiss"; - case HardwareCounter.BranchInstructionRetired: + case BranchInstructionRetired: return "branchInst"; - case HardwareCounter.BranchMispredictsRetired: + case BranchMispredictsRetired: return "branchMisp"; default: throw new NotSupportedException($"{hardwareCounter} has no short name mapping"); } } - public static bool TheGreaterTheBetter(this HardwareCounter hardwareCounter) + public static bool TheGreaterTheBetter(string hardwareCounter) { // this method could be just a return false as of today but we want to make sure that when we add new counter it's added here on purpose! switch (hardwareCounter) { - case HardwareCounter.Timer: - case HardwareCounter.TotalIssues: - case HardwareCounter.BranchInstructions: - case HardwareCounter.CacheMisses: - case HardwareCounter.BranchMispredictions: - case HardwareCounter.TotalCycles: - case HardwareCounter.UnhaltedCoreCycles: - case HardwareCounter.InstructionRetired: - case HardwareCounter.UnhaltedReferenceCycles: - case HardwareCounter.LlcReference: - case HardwareCounter.LlcMisses: - case HardwareCounter.BranchInstructionRetired: - case HardwareCounter.BranchMispredictsRetired: + case Timer: + case TotalIssues: + case BranchInstructions: + case CacheMisses: + case BranchMispredictions: + case TotalCycles: + case UnhaltedCoreCycles: + case InstructionRetired: + case UnhaltedReferenceCycles: + case LlcReference: + case LlcMisses: + case BranchInstructionRetired: + case BranchMispredictsRetired: return false; default: throw new NotSupportedException($"{hardwareCounter} has no TheGreaterTheBetter mapping"); diff --git a/src/BenchmarkDotNet/Diagnosers/PmcStats.cs b/src/BenchmarkDotNet/Diagnosers/PmcStats.cs index 0076fcf2e4..1aa2b97257 100644 --- a/src/BenchmarkDotNet/Diagnosers/PmcStats.cs +++ b/src/BenchmarkDotNet/Diagnosers/PmcStats.cs @@ -7,18 +7,18 @@ namespace BenchmarkDotNet.Diagnosers public class PmcStats { public long TotalOperations { get; set; } - public IReadOnlyDictionary Counters { get; } + public IReadOnlyDictionary Counters { get; } public IReadOnlyCollection CustomCounters { get; } private IReadOnlyDictionary CountersByProfileSourceId { get; } public PmcStats() { throw new InvalidOperationException("should never be used"); } - public PmcStats(IReadOnlyCollection hardwareCounters, Func factory) + public PmcStats(IReadOnlyCollection hardwareCounters, Func factory) : this(hardwareCounters, Array.Empty(), factory) { } - public PmcStats(IReadOnlyCollection hardwareCounters, IReadOnlyCollection customCounters, Func factory) + public PmcStats(IReadOnlyCollection hardwareCounters, IReadOnlyCollection customCounters, Func factory) { var hwCounters = hardwareCounters .Select(factory) diff --git a/src/BenchmarkDotNet/Diagnosers/PreciseMachineCounter.cs b/src/BenchmarkDotNet/Diagnosers/PreciseMachineCounter.cs index 3bd29b8cc1..6a38e6d485 100644 --- a/src/BenchmarkDotNet/Diagnosers/PreciseMachineCounter.cs +++ b/src/BenchmarkDotNet/Diagnosers/PreciseMachineCounter.cs @@ -8,25 +8,25 @@ public class PreciseMachineCounter { [PublicAPI] public int ProfileSourceId { get; } [PublicAPI] public string Name { get; } - [PublicAPI] public HardwareCounter Counter { get; } + [PublicAPI] public string Counter { get; } [PublicAPI] public CustomCounter? CustomCounter { get; } [PublicAPI] public int Interval { get; } [PublicAPI] public Dictionary PerInstructionPointer { get; } /// /// Gets the short name for display purposes. - /// For custom counters, uses the custom short name. For built-in counters, uses the enum's short name. + /// For custom counters, uses the custom short name. For built-in counters, uses the counter's short name. /// - [PublicAPI] public string ShortName => CustomCounter?.ShortName ?? Counter.ToShortName(); + [PublicAPI] public string ShortName => CustomCounter?.ShortName ?? HardwareCounter.ToShortName(Counter); /// /// Gets whether this counter tracks a metric where higher values are better. /// - [PublicAPI] public bool HigherIsBetter => CustomCounter?.HigherIsBetter ?? Counter.TheGreaterTheBetter(); + [PublicAPI] public bool HigherIsBetter => CustomCounter?.HigherIsBetter ?? HardwareCounter.TheGreaterTheBetter(Counter); public ulong Count { get; private set; } - internal PreciseMachineCounter(int profileSourceId, string name, HardwareCounter counter, int interval) + internal PreciseMachineCounter(int profileSourceId, string name, string counter, int interval) { ProfileSourceId = profileSourceId; Name = name; diff --git a/src/BenchmarkDotNet/Exporters/InstructionPointerExporter.cs b/src/BenchmarkDotNet/Exporters/InstructionPointerExporter.cs index c2a08fbc44..c054f730d0 100644 --- a/src/BenchmarkDotNet/Exporters/InstructionPointerExporter.cs +++ b/src/BenchmarkDotNet/Exporters/InstructionPointerExporter.cs @@ -74,7 +74,7 @@ private string Export(Summary summary, BenchmarkCase benchmarkCase, DisassemblyR /// there might be some hardware counter events not belonging to the benchmarked code (for example CLR or BenchmarkDotNet's Engine) /// to calculate the % per IP we need to know the total per benchmark, not per process /// - private static Dictionary SumHardwareCountersStatsOfBenchmarkedCode( + private static Dictionary SumHardwareCountersStatsOfBenchmarkedCode( DisassemblyResult disassemblyResult, PmcStats pmcStats) { IEnumerable Range(Asm asm) @@ -169,7 +169,7 @@ private static IReadOnlyList SumHardwareCountersPerMethod(Di return model; } - private void Export(ILogger logger, BenchmarkCase benchmarkCase, Dictionary totals, IReadOnlyList model, HardwareCounter[] hardwareCounters) + private void Export(ILogger logger, BenchmarkCase benchmarkCase, Dictionary totals, IReadOnlyList model, string[] hardwareCounters) { int columnsCount = hardwareCounters.Length + 1; @@ -191,7 +191,7 @@ private void Export(ILogger logger, BenchmarkCase benchmarkCase, Dictionary"); foreach (var hardwareCounter in hardwareCounters) - logger.WriteLine($"{hardwareCounter.ToShortName()}"); + logger.WriteLine($"{HardwareCounter.ToShortName(hardwareCounter)}"); logger.WriteLine(""); @@ -292,14 +292,14 @@ private static string GetShortRuntimeInfo(string fullInfo) private class CodeWithCounters { internal SourceCode Code { get; set; } - internal IReadOnlyDictionary SumPerCounter { get; set; } + internal IReadOnlyDictionary SumPerCounter { get; set; } } private class MethodWithCounters { internal DisassembledMethod Method { get; set; } internal IReadOnlyList> Instructions { get; set; } - internal IReadOnlyDictionary SumPerCounter { get; set; } + internal IReadOnlyDictionary SumPerCounter { get; set; } internal bool HasCounters => SumPerCounter.Values.Any(value => value != default); }