Skip to content
Permalink
Browse files

make it possible to not enforce power plan, move the revert to finall…

…y, simplify the code
  • Loading branch information
adamsitnik committed May 22, 2019
1 parent 063d1a5 commit 1578c5c60c3f59f9128f680e35d1db219aa60d8d
@@ -3,6 +3,7 @@
using BenchmarkDotNet.Engines;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Portability;
using BenchmarkDotNet.Running;

namespace BenchmarkDotNet.Environments
{
@@ -19,6 +20,7 @@ private EnvironmentResolver()
Register(EnvironmentMode.JitCharacteristic, RuntimeInformation.GetCurrentJit);
Register(EnvironmentMode.AffinityCharacteristic, RuntimeInformation.GetCurrentAffinity);
Register(EnvironmentMode.EnvironmentVariablesCharacteristic, Array.Empty<EnvironmentVariable>);
Register(EnvironmentMode.PowerPlanModeCharacteristic, () => PowerManagementApplier.Map(PowerPlan.HighPerformance));

// TODO: find a better place
Register(AccuracyMode.AnalyzeLaunchVarianceCharacteristic, () => false);
@@ -14,7 +14,7 @@ public sealed class EnvironmentMode : JobMode<EnvironmentMode>
public static readonly Characteristic<IntPtr> AffinityCharacteristic = CreateCharacteristic<IntPtr>(nameof(Affinity));
public static readonly Characteristic<GcMode> GcCharacteristic = CreateCharacteristic<GcMode>(nameof(Gc));
public static readonly Characteristic<IReadOnlyList<EnvironmentVariable>> EnvironmentVariablesCharacteristic = CreateCharacteristic<IReadOnlyList<EnvironmentVariable>>(nameof(EnvironmentVariables));
public static readonly Characteristic<PowerPlanMode> PowerPlanModeCharacteristic = CreateCharacteristic<PowerPlanMode>(nameof(PowerPlanMode));
public static readonly Characteristic<Guid> PowerPlanModeCharacteristic = CreateCharacteristic<Guid>(nameof(PowerPlanMode));

public static readonly EnvironmentMode Clr = new EnvironmentMode(Runtime.Clr).Freeze();
public static readonly EnvironmentMode Core = new EnvironmentMode(Runtime.Core).Freeze();
@@ -25,26 +25,23 @@ public sealed class EnvironmentMode : JobMode<EnvironmentMode>
public static readonly EnvironmentMode RyuJitX64 = new EnvironmentMode(nameof(RyuJitX64), Jit.RyuJit, Platform.X64).Freeze();
public static readonly EnvironmentMode RyuJitX86 = new EnvironmentMode(nameof(RyuJitX86), Jit.RyuJit, Platform.X86).Freeze();

[PublicAPI] public EnvironmentMode() : this(id: null) { }
[PublicAPI]
public EnvironmentMode() : this(id: null) { }

[PublicAPI] public EnvironmentMode(Runtime runtime) : this(runtime.ToString())
{
Runtime = runtime;
}
[PublicAPI]
public EnvironmentMode(Runtime runtime) : this(runtime.ToString()) => Runtime = runtime;

[PublicAPI] public EnvironmentMode(string id, Jit jit, Platform platform) : this(id)
[PublicAPI]
public EnvironmentMode(string id, Jit jit, Platform platform) : this(id)
{
Jit = jit;
Platform = platform;
if (jit == Jit.LegacyJit)
Runtime = Runtime.Clr;
}

[PublicAPI] public EnvironmentMode(string id) : base(id)
{
GcCharacteristic[this] = new GcMode();
PowerPlanModeCharacteristic[this] = new PowerPlanMode();
}
[PublicAPI]
public EnvironmentMode(string id) : base(id) => GcCharacteristic[this] = new GcMode();

/// <summary>
/// Platform (x86 or x64)
@@ -94,6 +91,16 @@ public IReadOnlyList<EnvironmentVariable> EnvironmentVariables
set => EnvironmentVariablesCharacteristic[this] = value;
}

/// <summary>
/// Power Plan Mode
/// </summary>
/// <remarks>Supported only on Windows.</remarks>
public Guid PowerPlanMode
{
get => PowerPlanModeCharacteristic[this];
set => PowerPlanModeCharacteristic[this] = value;
}

/// <summary>
/// Adds the specified <paramref name="variable"/> to <see cref="EnvironmentVariables"/>.
/// If <see cref="EnvironmentVariables"/> already contains a variable with the same key,
@@ -109,11 +116,5 @@ public void SetEnvironmentVariable(EnvironmentVariable variable)
newVariables.Add(variable);
EnvironmentVariables = newVariables;
}

public PowerPlanMode PowerPlanMode
{
get => PowerPlanModeCharacteristic[this];
set => PowerPlanModeCharacteristic[this] = value;
}
}
}
@@ -177,14 +177,20 @@ public static class JobExtensions
/// The default value is HighPerformance.
/// <remarks>Only available for Windows.</remarks>
/// </summary>
public static Job WithPowerPlan(this Job job, PowerPlan powerPlan) => job.WithCore(j => j.Environment.PowerPlanMode.PowerPlan = powerPlan);
public static Job WithPowerPlan(this Job job, PowerPlan powerPlan) => job.WithCore(j => j.Environment.PowerPlanMode = PowerManagementApplier.Map(powerPlan));

/// <summary>
/// Setting power plans by guid.
/// The default value is HighPerformance.
/// <remarks>Only available for Windows.</remarks>
/// </summary>
public static Job WithPowerPlan(this Job job, Guid powerPlanGuid) => job.WithCore(j => j.Environment.PowerPlanMode.PowerPlanGuid = powerPlanGuid);
public static Job WithPowerPlan(this Job job, Guid powerPlanGuid) => job.WithCore(j => j.Environment.PowerPlanMode = powerPlanGuid);


/// <summary>
/// ensures that BenchmarkDotNet does not enforce any power plan
/// </summary>
public static Job DontEnforcePowerPlan(this Job job) => job.WithCore(j => j.Environment.PowerPlanMode = Guid.Empty);

// Infrastructure
public static Job With(this Job job, IToolchain toolchain) => job.WithCore(j => j.Infrastructure.Toolchain = toolchain);

This file was deleted.

@@ -72,7 +72,7 @@ internal static Summary[] Run(BenchmarkRunInfo[] benchmarkRunInfos)
{
var runChronometer = Chronometer.Start();

var summary = Run(benchmarkRunInfo, benchmarkToBuildResult, resolver, compositeLogger, artifactsToCleanup, rootArtifactsFolderPath, resultsFolderPath, ref runChronometer);
var summary = Run(benchmarkRunInfo, benchmarkToBuildResult, resolver, compositeLogger, artifactsToCleanup, resultsFolderPath, ref runChronometer);

if (!benchmarkRunInfo.Config.Options.IsSet(ConfigOptions.JoinSummary))
PrintSummary(compositeLogger, benchmarkRunInfo.Config, summary);
@@ -118,60 +118,62 @@ internal static Summary[] Run(BenchmarkRunInfo[] benchmarkRunInfos)
IResolver resolver,
ILogger logger,
List<string> artifactsToCleanup,
string rootArtifactsFolderPath,
string resultsFolderPath,
ref StartedClock runChronometer)
{
var benchmarks = benchmarkRunInfo.BenchmarksCases;
var config = benchmarkRunInfo.Config;
var reports = new List<BenchmarkReport>();
string title = GetTitle(new[] { benchmarkRunInfo });
var powerManagementApplier = new PowerManagementApplier(logger);

logger.WriteLineInfo($"// Found {benchmarks.Length} benchmarks:");
foreach (var benchmark in benchmarks)
logger.WriteLineInfo($"// {benchmark.DisplayInfo}");
logger.WriteLine();
foreach (var benchmark in benchmarks)

using (var powerManagementApplier = new PowerManagementApplier(logger))
{
powerManagementApplier.ApplyPerformancePlan(benchmark.Job.Environment.PowerPlanMode);
var info = buildResults[benchmark];
var buildResult = info.buildResult;
foreach (var benchmark in benchmarks)
{
powerManagementApplier.ApplyPerformancePlan(benchmark.Job.Environment.PowerPlanMode);

if (!config.Options.IsSet(ConfigOptions.KeepBenchmarkFiles))
artifactsToCleanup.AddRange(buildResult.ArtifactsToCleanup);
var info = buildResults[benchmark];
var buildResult = info.buildResult;

if (buildResult.IsBuildSuccess)
{
var report = RunCore(benchmark, info.benchmarkId, logger, resolver, buildResult);
if (report.AllMeasurements.Any(m => m.Operations == 0))
throw new InvalidOperationException("An iteration with 'Operations == 0' detected");
reports.Add(report);
if (report.GetResultRuns().Any())
logger.WriteLineStatistic(report.GetResultRuns().GetStatistics().ToTimeStr(config.Encoding));

if (!report.Success && config.Options.IsSet(ConfigOptions.StopOnFirstError))
break;
}
else
{
reports.Add(new BenchmarkReport(false, benchmark, buildResult, buildResult, default, default, default, default));
if (!config.Options.IsSet(ConfigOptions.KeepBenchmarkFiles))
artifactsToCleanup.AddRange(buildResult.ArtifactsToCleanup);

if (buildResult.IsBuildSuccess)
{
var report = RunCore(benchmark, info.benchmarkId, logger, resolver, buildResult);
if (report.AllMeasurements.Any(m => m.Operations == 0))
throw new InvalidOperationException("An iteration with 'Operations == 0' detected");
reports.Add(report);
if (report.GetResultRuns().Any())
logger.WriteLineStatistic(report.GetResultRuns().GetStatistics().ToTimeStr(config.Encoding));

if (!report.Success && config.Options.IsSet(ConfigOptions.StopOnFirstError))
break;
}
else
{
reports.Add(new BenchmarkReport(false, benchmark, buildResult, buildResult, default, default, default, default));

if (buildResult.GenerateException != null)
logger.WriteLineError($"// Generate Exception: {buildResult.GenerateException.Message}");
if (buildResult.ErrorMessage != null)
logger.WriteLineError($"// Build Error: {buildResult.ErrorMessage}");
if (buildResult.GenerateException != null)
logger.WriteLineError($"// Generate Exception: {buildResult.GenerateException.Message}");
if (buildResult.ErrorMessage != null)
logger.WriteLineError($"// Build Error: {buildResult.ErrorMessage}");

if(config.Options.IsSet(ConfigOptions.StopOnFirstError))
break;
}
if (config.Options.IsSet(ConfigOptions.StopOnFirstError))
break;
}

logger.WriteLine();
logger.WriteLine();
}
}

var clockSpan = runChronometer.GetElapsed();

powerManagementApplier.ApplyUserPowerPlan();
return new Summary(title,
reports.ToImmutableArray(),
HostEnvironmentInfo.GetCurrent(),
@@ -2,50 +2,47 @@
using System.Collections.Generic;
using BenchmarkDotNet.Environments;
using BenchmarkDotNet.Helpers;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Loggers;
using BenchmarkDotNet.Portability;

namespace BenchmarkDotNet.Running
{
internal class PowerManagementApplier
internal class PowerManagementApplier : IDisposable
{
private readonly ILogger logger;
private Guid? userCurrentPowerPlan;
private bool powerPlanChanged = false;
private bool isInitialized = false;
private static readonly Dictionary<PowerPlan, Guid?> powerPlansDict = new Dictionary<PowerPlan, Guid?>()
private static readonly Guid UserPowerPlan = new Guid("67b4a053-3646-4532-affd-0535c9ea82a7");

private static readonly Dictionary<PowerPlan, Guid> powerPlansDict = new Dictionary<PowerPlan, Guid>()
{
{ PowerPlan.UserPowerPlan, null },
{ PowerPlan.UserPowerPlan, UserPowerPlan },
{ PowerPlan.HighPerformance, new Guid("8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c") },
{ PowerPlan.PowerSaver, new Guid("a1841308-3541-4fab-bc81-f71556f20b4a") },
{ PowerPlan.Balanced, new Guid("381b4222-f694-41f0-9685-ff5bb260df2e") },
{ PowerPlan.UltimatePerformance, new Guid("e9a42b02-d5df-448d-aa00-03f14749eb61") },
};

internal PowerManagementApplier(ILogger logger)
{
this.logger = logger;
}
private readonly ILogger logger;
private Guid? userCurrentPowerPlan;
private bool powerPlanChanged = false;
private bool isInitialized = false;

internal void ApplyPerformancePlan(PowerPlanMode powerPlanMode)
{
var guid = powerPlanMode.PowerPlanGuid == Guid.Empty ? powerPlansDict[powerPlanMode.PowerPlan] : powerPlanMode.PowerPlanGuid;
ApplyPerformancePlan(guid);
}
internal PowerManagementApplier(ILogger logger) => this.logger = logger;

public void Dispose() => ApplyUserPowerPlan();

internal void ApplyPerformancePlan(Guid? guid)
internal static Guid Map(PowerPlan value) => powerPlansDict[value];

internal void ApplyPerformancePlan(Guid id)
{
if (RuntimeInformation.IsWindows())
{
if (guid != null && powerPlanChanged == false)
ApplyPlanByGuid(guid.Value);
else if (guid == null)
ApplyUserPowerPlan();
}
if (!RuntimeInformation.IsWindows() || id == Guid.Empty)
return;

if (!powerPlanChanged && id != UserPowerPlan)
ApplyPlanByGuid(id);
else
ApplyUserPowerPlan();
}

internal void ApplyUserPowerPlan()
private void ApplyUserPowerPlan()
{
if (powerPlanChanged && RuntimeInformation.IsWindows())
{
@@ -1,12 +1,8 @@
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Environments;
using BenchmarkDotNet.Environments;
using BenchmarkDotNet.Helpers;
using BenchmarkDotNet.Portability;
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Tests.Loggers;
using BenchmarkDotNet.Tests.XUnit;
using System.Threading;
using Xunit;
using Xunit.Abstractions;

@@ -24,14 +20,13 @@ public void TestSettingAndRevertingBackGuid()
var userPlan = PowerManagementHelper.CurrentPlan;
var logger = new OutputLogger(Output);
var powerManagementApplier = new PowerManagementApplier(logger);
var config = DefaultConfig.Instance.With(logger);
powerManagementApplier.ApplyPerformancePlan(new Jobs.PowerPlanMode()
{
PowerPlan = PowerPlan.HighPerformance
});

powerManagementApplier.ApplyPerformancePlan(PowerManagementApplier.Map(PowerPlan.HighPerformance));

Assert.Equal(HighPerformancePlanGuid, PowerManagementHelper.CurrentPlan.ToString());
Assert.Equal("High performance", PowerManagementHelper.CurrentPlanFriendlyName);
powerManagementApplier.ApplyUserPowerPlan();
powerManagementApplier.Dispose();

Assert.Equal(userPlan, PowerManagementHelper.CurrentPlan);
}

@@ -41,13 +36,12 @@ public void TestPowerPlanShouldNotChange()
var userPlan = PowerManagementHelper.CurrentPlan;
var logger = new OutputLogger(Output);
var powerManagementApplier = new PowerManagementApplier(logger);
var config = DefaultConfig.Instance.With(logger);
powerManagementApplier.ApplyPerformancePlan(new Jobs.PowerPlanMode()
{
PowerPlan = PowerPlan.UserPowerPlan
});

powerManagementApplier.ApplyPerformancePlan(PowerManagementApplier.Map(PowerPlan.UserPowerPlan));

Assert.Equal(userPlan.ToString(), PowerManagementHelper.CurrentPlan.ToString());
powerManagementApplier.ApplyUserPowerPlan();
powerManagementApplier.Dispose();

Assert.Equal(userPlan, PowerManagementHelper.CurrentPlan);
}
}

0 comments on commit 1578c5c

Please sign in to comment.
You can’t perform that action at this time.