Skip to content

Commit

Permalink
Bump Perfolizer + Initial Phd adoption
Browse files Browse the repository at this point in the history
This commit is a first step of the grand API refactoring.

* Cpu Detection Upgrade
  * All CPU-related detection logic moved from RuntimeInformation to CpuDetector
  * BrandString formatting moved to Perfolizer (see CpuBrandHelper)
  * New serializable class for Cpu information: PhdCpu from Perfolizer
* Os Detection Upgrade
  * All OS-related detection logic moved from RuntimeInformation to OsDetector
  * BrandString formatting moved to Perfolizer (see OsBrandHelper)
  * New serializable class for Os information: PhdOs from Perfolizer
* Initial adoption of Phd (Performance History Data)
  * Phd from Perfolizer is our future way to keep and process gathered data and measurements
  * Only the initial implementation is available, it still misses a lot of features
  * Examples of Phd json and corresponding new Summary Tables are in
    BenchmarkDotNet/tests/BenchmarkDotNet.Tests/Phd/VerifiedFiles/Phd.PhdTableTest*
  * Phd can be tried via [PhdExporter]
  * Documentation is coming once we have a more complete implementation
  • Loading branch information
AndreyAkinshin committed Aug 27, 2024
1 parent a58872b commit 9cbeb18
Show file tree
Hide file tree
Showing 133 changed files with 8,619 additions and 1,393 deletions.
3 changes: 2 additions & 1 deletion src/BenchmarkDotNet.Diagnostics.Windows/HardwareCounters.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using BenchmarkDotNet.Detectors;
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Portability;
using BenchmarkDotNet.Toolchains.InProcess.Emit;
Expand Down Expand Up @@ -31,7 +32,7 @@ private static readonly Dictionary<HardwareCounter, string> EtwTranslations

public static IEnumerable<ValidationError> Validate(ValidationParameters validationParameters, bool mandatory)
{
if (!RuntimeInformation.IsWindows())
if (!OsDetector.IsWindows())
{
yield return new ValidationError(true, "Hardware Counters and EtwProfiler are supported only on Windows");
yield break;
Expand Down
3 changes: 2 additions & 1 deletion src/BenchmarkDotNet.Diagnostics.Windows/JitDiagnoser.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using BenchmarkDotNet.Detectors;
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Engines;
using BenchmarkDotNet.Loggers;
Expand Down Expand Up @@ -33,7 +34,7 @@ public void Handle(HostSignal signal, DiagnoserActionParameters parameters)

public IEnumerable<ValidationError> Validate(ValidationParameters validationParameters)
{
if (!RuntimeInformation.IsWindows())
if (!OsDetector.IsWindows())
{
yield return new ValidationError(true, $"{GetType().Name} is supported only on Windows");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
using System.Collections.Immutable;
using System.Linq;
using BenchmarkDotNet.Analysers;
using BenchmarkDotNet.Detectors;
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Engines;
using BenchmarkDotNet.Exporters;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Loggers;
using BenchmarkDotNet.Portability;
using BenchmarkDotNet.Reports;
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Validators;
Expand Down Expand Up @@ -124,10 +124,10 @@ internal static bool IsSupported(RuntimeMoniker runtimeMoniker)
case RuntimeMoniker.NetCoreApp20:
case RuntimeMoniker.NetCoreApp21:
case RuntimeMoniker.NetCoreApp22:
return RuntimeInformation.IsWindows();
return OsDetector.IsWindows();
case RuntimeMoniker.NetCoreApp30:
case RuntimeMoniker.NetCoreApp31:
return RuntimeInformation.IsWindows() || RuntimeInformation.IsLinux();
return OsDetector.IsWindows() || OsDetector.IsLinux();
default:
throw new ArgumentOutOfRangeException(nameof(runtimeMoniker), runtimeMoniker, $"Runtime moniker {runtimeMoniker} is not supported");
}
Expand Down
6 changes: 3 additions & 3 deletions src/BenchmarkDotNet.Diagnostics.dotTrace/DotTraceDiagnoser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
using System.Collections.Immutable;
using System.Linq;
using BenchmarkDotNet.Analysers;
using BenchmarkDotNet.Detectors;
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Engines;
using BenchmarkDotNet.Exporters;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Loggers;
using BenchmarkDotNet.Portability;
using BenchmarkDotNet.Reports;
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Toolchains;
Expand Down Expand Up @@ -118,10 +118,10 @@ internal static bool IsSupported(RuntimeMoniker runtimeMoniker)
case RuntimeMoniker.NetCoreApp20:
case RuntimeMoniker.NetCoreApp21:
case RuntimeMoniker.NetCoreApp22:
return RuntimeInformation.IsWindows();
return OsDetector.IsWindows();
case RuntimeMoniker.NetCoreApp30:
case RuntimeMoniker.NetCoreApp31:
return RuntimeInformation.IsWindows() || RuntimeInformation.IsLinux();
return OsDetector.IsWindows() || OsDetector.IsLinux();
default:
throw new ArgumentOutOfRangeException(nameof(runtimeMoniker), runtimeMoniker, $"Runtime moniker {runtimeMoniker} is not supported");
}
Expand Down
2 changes: 1 addition & 1 deletion src/BenchmarkDotNet/Analysers/ZeroMeasurementAnalyser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ private ZeroMeasurementAnalyser() { }

protected override IEnumerable<Conclusion> AnalyseReport(BenchmarkReport report, Summary summary)
{
var currentFrequency = summary.HostEnvironmentInfo.CpuInfo.Value.MaxFrequency;
var currentFrequency = summary.HostEnvironmentInfo.Cpu.Value.MaxFrequency();
if (!currentFrequency.HasValue || currentFrequency <= 0)
currentFrequency = FallbackCpuResolutionValue.ToFrequency();

Expand Down
10 changes: 10 additions & 0 deletions src/BenchmarkDotNet/Attributes/Exporters/PhdExporterAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System;
using BenchmarkDotNet.Exporters;

namespace BenchmarkDotNet.Attributes;

/// <summary>
/// IMPORTANT: Not fully implemented yet
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Assembly, AllowMultiple = true)]
public class PhdExporterAttribute() : ExporterConfigBaseAttribute(new PhdJsonExporter(), new PhdMdExporter());
3 changes: 1 addition & 2 deletions src/BenchmarkDotNet/BenchmarkDotNet.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,13 @@
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Templates\*" Exclude="bin\**;obj\**;**\*.xproj;packages\**;@(EmbeddedResource)" />
<EmbeddedResource Include="Environments\microarchitectures.txt" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.9.1" />
<PackageReference Include="Gee.External.Capstone" Version="2.3.0" />
<PackageReference Include="Iced" Version="1.17.0" />
<PackageReference Include="Microsoft.Diagnostics.Runtime" Version="2.2.332302" />
<PackageReference Include="Perfolizer" Version="[0.3.17]" />
<PackageReference Include="Perfolizer" Version="[0.4.0]" />
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="3.1.8" PrivateAssets="contentfiles;analyzers" />
<PackageReference Include="Microsoft.DotNet.PlatformAbstractions" Version="3.1.6" />
<!-- Do not update these packages, or else netcoreapp3.0 and older will no longer work -->
Expand Down
3 changes: 2 additions & 1 deletion src/BenchmarkDotNet/Configs/DefaultConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.IO;
using BenchmarkDotNet.Analysers;
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Detectors;
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.EventProcessors;
using BenchmarkDotNet.Exporters;
Expand Down Expand Up @@ -90,7 +91,7 @@ public string ArtifactsPath
{
get
{
var root = RuntimeInformation.IsAndroid() ?
var root = OsDetector.IsAndroid() ?
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) :
Directory.GetCurrentDirectory();
return Path.Combine(root, "BenchmarkDotNet.Artifacts");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Numerics;
using BenchmarkDotNet.Environments;
using System.Text;

using BenchmarkDotNet.Environments;
#if NET6_0_OR_GREATER
using System.Runtime.Intrinsics.X86;
using System.Runtime.Intrinsics.Arm;
#endif

namespace BenchmarkDotNet.Portability.Cpu
namespace BenchmarkDotNet.Detectors.Cpu
{
internal static class HardwareIntrinsics
{
Expand Down
12 changes: 12 additions & 0 deletions src/BenchmarkDotNet/Detectors/Cpu/ICpuDetector.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Perfolizer.Phd.Dto;

namespace BenchmarkDotNet.Detectors.Cpu;

/// <summary>
/// Loads the <see cref="PhdCpu"/> for the current hardware
/// </summary>
public interface ICpuDetector
{
bool IsApplicable();
PhdCpu? Detect();
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
using System.Collections.Generic;
using BenchmarkDotNet.Helpers;
using BenchmarkDotNet.Portability;
using Perfolizer.Phd.Dto;

namespace BenchmarkDotNet.Portability.Cpu.Linux;
namespace BenchmarkDotNet.Detectors.Cpu.Linux;

/// <summary>
/// CPU information from output of the `cat /proc/cpuinfo` and `lscpu` command.
/// Linux only.
/// </summary>
internal class LinuxCpuInfoDetector : ICpuInfoDetector
internal class LinuxCpuDetector : ICpuDetector
{
public bool IsApplicable() => RuntimeInformation.IsLinux();
public bool IsApplicable() => OsDetector.IsLinux();

public CpuInfo? Detect()
public PhdCpu? Detect()
{
if (!IsApplicable()) return null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
using System.Text.RegularExpressions;
using BenchmarkDotNet.Extensions;
using BenchmarkDotNet.Helpers;
using BenchmarkDotNet.Portability;
using Perfolizer.Horology;
using Perfolizer.Phd.Dto;

namespace BenchmarkDotNet.Portability.Cpu.Linux;
namespace BenchmarkDotNet.Detectors.Cpu.Linux;

internal static class LinuxCpuInfoParser
{
Expand All @@ -26,7 +28,7 @@ private static class Lscpu

/// <param name="cpuInfo">Output of `cat /proc/cpuinfo`</param>
/// <param name="lscpu">Output of `lscpu`</param>
internal static CpuInfo Parse(string? cpuInfo, string? lscpu)
internal static PhdCpu Parse(string? cpuInfo, string? lscpu)
{
var processorModelNames = new HashSet<string>();
var processorsToPhysicalCoreCount = new Dictionary<string, int>();
Expand Down Expand Up @@ -87,13 +89,15 @@ internal static CpuInfo Parse(string? cpuInfo, string? lscpu)
string processorName = processorModelNames.Count > 0 ? string.Join(", ", processorModelNames) : null;
int? physicalProcessorCount = processorsToPhysicalCoreCount.Count > 0 ? processorsToPhysicalCoreCount.Count : null;
int? physicalCoreCount = processorsToPhysicalCoreCount.Count > 0 ? processorsToPhysicalCoreCount.Values.Sum() : coresPerSocket;
return new CpuInfo(
processorName,
physicalProcessorCount,
physicalCoreCount,
logicalCoreCount > 0 ? logicalCoreCount : null,
nominalFrequency,
maxFrequency);
return new PhdCpu
{
ProcessorName = processorName,
PhysicalProcessorCount = physicalProcessorCount,
PhysicalCoreCount = physicalCoreCount,
LogicalCoreCount = logicalCoreCount > 0 ? logicalCoreCount : null,
NominalFrequencyHz = nominalFrequency?.Hertz.RoundToLong(),
MaxFrequencyHz = maxFrequency?.Hertz.RoundToLong()
};
}

internal static Frequency? ParseFrequencyFromBrandString(string brandString)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Management;
using BenchmarkDotNet.Extensions;
using BenchmarkDotNet.Portability;
using Perfolizer.Horology;
using Perfolizer.Phd.Dto;

namespace BenchmarkDotNet.Portability.Cpu.Windows;
namespace BenchmarkDotNet.Detectors.Cpu.Windows;

internal class MosCpuInfoDetector : ICpuInfoDetector
internal class MosCpuDetector : ICpuDetector
{
#if NET6_0_OR_GREATER
[System.Runtime.Versioning.SupportedOSPlatform("windows")]
#endif
public bool IsApplicable() => RuntimeInformation.IsWindows() &&
public bool IsApplicable() => OsDetector.IsWindows() &&
RuntimeInformation.IsFullFramework &&
!RuntimeInformation.IsMono;

#if NET6_0_OR_GREATER
[System.Runtime.Versioning.SupportedOSPlatform("windows")]
#endif
public CpuInfo? Detect()
public PhdCpu? Detect()
{
if (!IsApplicable()) return null;

Expand Down Expand Up @@ -49,11 +51,14 @@ public bool IsApplicable() => RuntimeInformation.IsWindows() &&
? Frequency.FromMHz(sumMaxFrequency * 1.0 / processorsCount)
: null;

return new CpuInfo(
processorName,
GetCount(processorsCount), GetCount(physicalCoreCount), GetCount(logicalCoreCount),
maxFrequency, maxFrequency);

int? GetCount(int count) => count > 0 ? count : null;
return new PhdCpu
{
ProcessorName = processorName,
PhysicalProcessorCount = processorsCount > 0 ? processorsCount : null,
PhysicalCoreCount = physicalCoreCount > 0 ? physicalCoreCount : null,
LogicalCoreCount = logicalCoreCount > 0 ? logicalCoreCount : null,
NominalFrequencyHz = maxFrequency?.Hertz.RoundToLong(),
MaxFrequencyHz = maxFrequency?.Hertz.RoundToLong()
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace BenchmarkDotNet.Detectors.Cpu.Windows;

internal class WindowsCpuDetector() : CpuDetector(new MosCpuDetector(), new WmicCpuDetector());
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
using System.IO;
using BenchmarkDotNet.Helpers;
using BenchmarkDotNet.Portability;
using Perfolizer.Phd.Dto;

namespace BenchmarkDotNet.Portability.Cpu.Windows;
namespace BenchmarkDotNet.Detectors.Cpu.Windows;

/// <summary>
/// CPU information from output of the `wmic cpu get Name, NumberOfCores, NumberOfLogicalProcessors /Format:List` command.
/// Windows only.
/// </summary>
internal class WmicCpuInfoDetector : ICpuInfoDetector
internal class WmicCpuDetector : ICpuDetector
{
private const string DefaultWmicPath = @"C:\Windows\System32\wbem\WMIC.exe";

public bool IsApplicable() => RuntimeInformation.IsWindows();
public bool IsApplicable() => OsDetector.IsWindows();

public CpuInfo? Detect()
public PhdCpu? Detect()
{
if (!IsApplicable()) return null;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace BenchmarkDotNet.Portability.Cpu.Windows;
namespace BenchmarkDotNet.Detectors.Cpu.Windows;

internal static class WmicCpuInfoKeyNames
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
using System.Collections.Generic;
using BenchmarkDotNet.Extensions;
using BenchmarkDotNet.Helpers;
using Perfolizer.Horology;
using Perfolizer.Phd.Dto;

namespace BenchmarkDotNet.Portability.Cpu.Windows;
namespace BenchmarkDotNet.Detectors.Cpu.Windows;

internal static class WmicCpuInfoParser
{
/// <summary>
/// Parses wmic output and returns <see cref="CpuInfo"/>
/// Parses wmic output and returns <see cref="PhdCpu"/>
/// </summary>
/// <param name="wmicOutput">Output of `wmic cpu get Name, NumberOfCores, NumberOfLogicalProcessors /Format:List`</param>
internal static CpuInfo Parse(string? wmicOutput)
internal static PhdCpu Parse(string? wmicOutput)
{
var processorModelNames = new HashSet<string>();
int physicalCoreCount = 0;
Expand Down Expand Up @@ -50,11 +52,14 @@ internal static CpuInfo Parse(string? wmicOutput)
? Frequency.FromMHz(sumMaxFrequency / processorsCount)
: null;

return new CpuInfo(
processorName,
GetCount(processorsCount), GetCount(physicalCoreCount), GetCount(logicalCoreCount),
maxFrequency, maxFrequency);

int? GetCount(int count) => count > 0 ? count : null;
return new PhdCpu
{
ProcessorName = processorName,
PhysicalProcessorCount = processorsCount > 0 ? processorsCount : null,
PhysicalCoreCount = physicalCoreCount > 0 ? physicalCoreCount : null,
LogicalCoreCount = logicalCoreCount > 0 ? logicalCoreCount : null,
NominalFrequencyHz = maxFrequency?.Hertz.RoundToLong(),
MaxFrequencyHz = maxFrequency?.Hertz.RoundToLong()
};
}
}
Loading

0 comments on commit 9cbeb18

Please sign in to comment.