Skip to content

Instantly share code, notes, and snippets.

@JohannesDeml
Forked from MarkPflug/CpuDiagnoser.cs
Created January 5, 2023 16:28
Show Gist options
  • Save JohannesDeml/8deadfff8feee8b5a03da06100213f21 to your computer and use it in GitHub Desktop.
Save JohannesDeml/8deadfff8feee8b5a03da06100213f21 to your computer and use it in GitHub Desktop.

Revisions

  1. @MarkPflug MarkPflug created this gist Dec 6, 2021.
    107 changes: 107 additions & 0 deletions CpuDiagnoser.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,107 @@
    using BenchmarkDotNet.Analysers;
    using BenchmarkDotNet.Columns;
    using BenchmarkDotNet.Configs;
    using BenchmarkDotNet.Diagnosers;
    using BenchmarkDotNet.Engines;
    using BenchmarkDotNet.Exporters;
    using BenchmarkDotNet.Loggers;
    using BenchmarkDotNet.Reports;
    using BenchmarkDotNet.Running;
    using BenchmarkDotNet.Validators;
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;

    namespace Benchmarks
    {
    public class CpuDiagnoserAttribute : Attribute, IConfigSource
    {
    public IConfig Config { get; }

    public CpuDiagnoserAttribute()
    {
    Config = ManualConfig.CreateEmpty().AddDiagnoser(new CpuDiagnoser());
    }
    }

    public class CpuDiagnoser : IDiagnoser
    {
    Process proc;

    public CpuDiagnoser()
    {
    this.proc = Process.GetCurrentProcess();
    }

    public IEnumerable<string> Ids => new[] { "CPU" };

    public IEnumerable<IExporter> Exporters => Array.Empty<IExporter>();

    public IEnumerable<IAnalyser> Analysers => Array.Empty<IAnalyser>();

    public void DisplayResults(ILogger logger)
    {
    }

    public RunMode GetRunMode(BenchmarkCase benchmarkCase)
    {
    return RunMode.NoOverhead;
    }

    long userStart, userEnd;
    long privStart, privEnd;

    public void Handle(HostSignal signal, DiagnoserActionParameters parameters)
    {
    if(signal == HostSignal.BeforeActualRun)
    {
    userStart = proc.UserProcessorTime.Ticks;
    privStart = proc.PrivilegedProcessorTime.Ticks;
    }
    if(signal == HostSignal.AfterActualRun)
    {
    userEnd = proc.UserProcessorTime.Ticks;
    privEnd = proc.PrivilegedProcessorTime.Ticks;
    }
    }

    public IEnumerable<Metric> ProcessResults(DiagnoserResults results)
    {
    yield return new Metric(CpuUserMetricDescriptor.Instance, (userEnd - userStart) * 100d / results.TotalOperations);
    yield return new Metric(CpuPrivilegedMetricDescriptor.Instance, (privEnd - privStart) * 100d / results.TotalOperations);
    }

    public IEnumerable<ValidationError> Validate(ValidationParameters validationParameters)
    {
    yield break;
    }

    class CpuUserMetricDescriptor : IMetricDescriptor
    {
    internal static readonly IMetricDescriptor Instance = new CpuUserMetricDescriptor();

    public string Id => "CPU User Time";
    public string DisplayName => Id;
    public string Legend => Id;
    public string NumberFormat => "0.##";
    public UnitType UnitType => UnitType.Time;
    public string Unit => "ns";
    public bool TheGreaterTheBetter => false;
    public int PriorityInCategory => 1;
    }

    class CpuPrivilegedMetricDescriptor : IMetricDescriptor
    {
    internal static readonly IMetricDescriptor Instance = new CpuPrivilegedMetricDescriptor();

    public string Id => "CPU Privileged Time";
    public string DisplayName => Id;
    public string Legend => Id;
    public string NumberFormat => "0.##";
    public UnitType UnitType => UnitType.Time;
    public string Unit => "ns";
    public bool TheGreaterTheBetter => false;
    public int PriorityInCategory => 1;
    }
    }
    }