diff options
Diffstat (limited to 'src')
7 files changed, 196 insertions, 385 deletions
diff --git a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj index 8c5034c..873cde4 100644 --- a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj +++ b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj @@ -305,7 +305,7 @@ <Compile Include="OpenId\UriIdentifierTests.cs" /> <Compile Include="OpenId\XriIdentifierTests.cs" /> <Compile Include="Performance\CodeTimers.cs" /> - <Compile Include="Performance\PerformanceMeasurement.cs" /> + <Compile Include="Performance\HighPerformance.cs" /> <Compile Include="Performance\PerformanceTestUtilities.cs" /> <Compile Include="Performance\PowerManagement.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> diff --git a/src/DotNetOpenAuth.Test/OpenId/Provider/PerformanceTests.cs b/src/DotNetOpenAuth.Test/OpenId/Provider/PerformanceTests.cs index fb1125e..d35ac1d 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Provider/PerformanceTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Provider/PerformanceTests.cs @@ -18,8 +18,8 @@ namespace DotNetOpenAuth.Test.OpenId.Provider { using DotNetOpenAuth.OpenId.ChannelElements; using DotNetOpenAuth.OpenId.Messages; using DotNetOpenAuth.OpenId.Provider; - using NUnit.Framework; using DotNetOpenAuth.Test.Performance; + using NUnit.Framework; [TestFixture, Category("Performance")] public class PerformanceTests : OpenIdTestBase { diff --git a/src/DotNetOpenAuth.Test/Performance/CodeTimers.cs b/src/DotNetOpenAuth.Test/Performance/CodeTimers.cs index 78f8766..85fa83d 100644 --- a/src/DotNetOpenAuth.Test/Performance/CodeTimers.cs +++ b/src/DotNetOpenAuth.Test/Performance/CodeTimers.cs @@ -1,3 +1,4 @@ +// <auto-generated/> // well, imported. But this gets StyleCop off our back //----------------------------------------------------------------------- // <copyright file="CodeTimers.cs" company="Microsoft Corporation"> // Copyright (c) Microsoft Corporation. All rights reserved. @@ -15,9 +16,20 @@ namespace DotNetOpenAuth.Test.Performance { /// statistics on this list (Mean, Median, StandardDeviation ...) /// </summary> internal class Stats : IEnumerable<float> { + private List<float> data; + private float minimum; + private float maximum; + private float median; + private float mean; + private float standardDeviation; + private bool statsComputed; + public Stats() { data = new List<float>(); } - public void Add(float dataItem) { statsComputed = false; data.Add(dataItem); } + public void Add(float dataItem) { + statsComputed = false; + data.Add(dataItem); + } public void RemoveRange(int index, int count) { data.RemoveRange(index, count); statsComputed = false; @@ -37,22 +49,71 @@ namespace DotNetOpenAuth.Test.Performance { public IEnumerator<float> GetEnumerator() { return data.GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return data.GetEnumerator(); } - public float Minimum { get { if (!statsComputed) ComputeStats(); return minimum; } } - public float Maximum { get { if (!statsComputed) ComputeStats(); return maximum; } } - public float Median { get { if (!statsComputed) ComputeStats(); return median; } } - public float Mean { get { if (!statsComputed) ComputeStats(); return mean; } } - public float StandardDeviation { get { if (!statsComputed) ComputeStats(); return standardDeviation; } } + public float Minimum { + get { + if (!statsComputed) { + this.ComputeStats(); + } + + return minimum; + } + } + public float Maximum { + get { + if (!statsComputed) { + this.ComputeStats(); + } + + return maximum; + } + } + public float Median { + get { + if (!statsComputed) { + this.ComputeStats(); + } + + return median; + } + } + + public float Mean { + get { + if (!statsComputed) { + this.ComputeStats(); + } + + return mean; + } + } + + public float StandardDeviation { + get { + if (!statsComputed) { + this.ComputeStats(); + } + + return standardDeviation; + } + } + + /// <summary> + /// Returns a <see cref="System.String"/> that represents this instance. + /// </summary> + /// <returns> + /// A <see cref="System.String"/> that represents this instance. + /// </returns> public override string ToString() { - if (!statsComputed) + if (!statsComputed) { ComputeStats(); + } + return "mean=" + mean.ToString("f3") + " median=" + median.ToString("f3") + " min=" + minimum.ToString("f3") + " max=" + maximum.ToString("f3") + " sdtdev=" + standardDeviation.ToString("f3") + " samples=" + Count.ToString(); } - #region privates - - public void ComputeStats() { + private void ComputeStats() { minimum = float.MaxValue; maximum = float.MinValue; median = 0.0F; @@ -86,15 +147,6 @@ namespace DotNetOpenAuth.Test.Performance { statsComputed = true; } - - List<float> data; - float minimum; - float maximum; - float median; - float mean; - float standardDeviation; - bool statsComputed; - #endregion }; /// <summary> @@ -225,8 +277,8 @@ namespace DotNetOpenAuth.Test.Performance { // mode so so that we get more stable results. // TODO: see if this is true, and if there is a better way of doing it. Stopwatch sw = Stopwatch.StartNew(); - while (sw.ElapsedMilliseconds < 32) - ; + while (sw.ElapsedMilliseconds < 32) { + } } /// <summary> /// The number of times the benchmark is run in a loop for a single measument. diff --git a/src/DotNetOpenAuth.Test/Performance/HighPerformance.cs b/src/DotNetOpenAuth.Test/Performance/HighPerformance.cs new file mode 100644 index 0000000..32b4cfa --- /dev/null +++ b/src/DotNetOpenAuth.Test/Performance/HighPerformance.cs @@ -0,0 +1,69 @@ +//----------------------------------------------------------------------- +// <copyright file="HighPerformance.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.Test.Performance { + using System; + using System.Diagnostics; + using System.Threading; + using log4net; + using NUnit.Framework; + + /// <summary> + /// Suppresses logging and forces the CPU into a high performance mode. + /// </summary> + internal class HighPerformance : IDisposable { + private readonly log4net.Core.Level originalLoggerThreshold; + private readonly PowerManagment.PowerSetting powerSetting; + private readonly ProcessPriorityClass originalProcessPriority; + +#pragma warning disable 0618 + /// <summary> + /// Initializes a new instance of the <see cref="HighPerformance"/> class. + /// </summary> + internal HighPerformance() { + if (!PerformanceTestUtilities.CoolOff()) { + Assert.Inconclusive("Timed out waiting for a quiet CPU in which to perform perf tests."); + } + + this.originalLoggerThreshold = LogManager.GetLoggerRepository().Threshold; + LogManager.GetLoggerRepository().Threshold = LogManager.GetLoggerRepository().LevelMap["OFF"]; + this.powerSetting = new PowerManagment.PowerSetting(PowerManagment.PowerProfiles.HighPerformance); + this.originalProcessPriority = Process.GetCurrentProcess().PriorityClass; + Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High; + Thread.CurrentThread.Priority = ThreadPriority.Highest; + HighCpu(); + } + + /// <summary> + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// </summary> + public void Dispose() { + Thread.CurrentThread.Priority = ThreadPriority.Normal; + Process.GetCurrentProcess().PriorityClass = this.originalProcessPriority; + this.powerSetting.Dispose(); // restores original power setting. + LogManager.GetLoggerRepository().Threshold = this.originalLoggerThreshold; + } +#pragma warning restore 0618 + + /// <summary> + /// Runs the CPU in a tight loop to get it out of any low power state. + /// </summary> + private static void HighCpu() { + int dummy; + new MultiSampleCodeTimer(10, 1000).Measure( + "Loop 1K times", + 1, + delegate { + int k = 0; + while (k < 1000) { + k++; // still in danger of being optimized. + } + + dummy = k; // avoid optimization. + }); + } + } +} diff --git a/src/DotNetOpenAuth.Test/Performance/PerformanceMeasurement.cs b/src/DotNetOpenAuth.Test/Performance/PerformanceMeasurement.cs deleted file mode 100644 index 6199005..0000000 --- a/src/DotNetOpenAuth.Test/Performance/PerformanceMeasurement.cs +++ /dev/null @@ -1,268 +0,0 @@ -//----------------------------------------------------------------------- -// <copyright file="CodeTimers.cs" company="Microsoft Corporation"> -// Copyright (c) Microsoft Corporation. All rights reserved. -// </copyright> -// <author>Vance Morrison</author> -//----------------------------------------------------------------------- - -namespace DotNetOpenAuth.Test.Performance { - using System; - using System.Collections.Generic; - using System.Text; - using System.IO; - using System.Web; // for HttpUtility.HtmlEncode - using System.Reflection; // for Assembly - using System.Diagnostics; // for Process, DebuggableAttribute - - /// <summary> - /// A code:StatsLogger is something that remembers a set of common - /// atrributes (verison of the code, Machine used, NGENed or JITed ...) as - /// well as a set of performance results from mulitple benchmarks. - /// (represented by a code:StatsCollection) - /// - /// The primary value of a StatsLogger is the - /// code:StatsLogger.DisplayHtmlReport which displayes the data in a - /// user-friendly way. - /// </summary> - internal class StatsLogger { - public StatsLogger(StatsCollection dataSet) { - this.dataSet = dataSet; - attributes = new Dictionary<string, object>(); - } - StatsCollection DataSet { get { return dataSet; } } - public object this[string key] { - get { return attributes[key]; } - set { attributes[key] = value; } - } - public void Add(string name, Stats sample) { dataSet.Add(name, sample); } - public string Category { - get { return category; } - set { category = value; } - } - public void AddWithCount(string name, int iterationCount, float scale, Stats sample) { - if (!string.IsNullOrEmpty(category)) - name = category + ": " + name; - if (iterationCount != 1 || scale != 1) { - name += " ["; - if (iterationCount != 1) { - name = name + "count=" + iterationCount.ToString(); - if (scale != 1) - name += " "; - } - if (scale != 1) - name = name + " scale=" + scale.ToString("f1"); - name += "]"; - } - - Add(name, sample); - } - public void DisplayHtmlReport(string reportFileName) { - TextWriter writer = File.CreateText(reportFileName); - - writer.WriteLine("<html>"); - writer.WriteLine("<h1> MeasureIt Performance Results </h1>"); - object optimizationValue; - if (attributes.TryGetValue("CodeOptimization", out optimizationValue) && ((string)optimizationValue) == "Unoptimized") { - writer.WriteLine("<font color=red><p>"); - writer.WriteLine("Warning: the MeasureIt code was not optimized. The results are likely invalid."); - writer.WriteLine("</p></font>"); - } - if (Environment.OSVersion.Version.Major < 6) { - writer.WriteLine("<b><p>"); - writer.WriteLine("Data was collected on a Pre-Vista machine. MeasureIt does NOT automatically"); - writer.WriteLine("set the CPU to a high performance power policy. This means the CPU might"); - writer.WriteLine("be throttled to save power and can lead to"); - writer.WriteLine("incorrect and inconsistant benchmark measurements."); - writer.WriteLine("</p></b>"); - } else if (PowerManagment.CurrentPolicy != PowerManagment.PowerProfiles.HighPerformance) { - writer.WriteLine("<font color=red><p>"); - writer.WriteLine("Warning: The power policy settings were not set at 'High Performance' during this run."); - writer.WriteLine("This means that the CPU could be throttled to lower frequency resulting in"); - writer.WriteLine("incorrect and inconsistant benchmark measurements."); - writer.WriteLine("To correct go to Start Menu -> Contol Panel -> System and Maintance -> Power Options"); - writer.WriteLine("and set the power policy to 'High Performance' for the duration of the tests."); - writer.WriteLine("</p></font>"); - } - writer.WriteLine("<p>"); - writer.WriteLine("Below are the results of running a series of benchmarks. Use the"); - writer.WriteLine("<b>MeasureIt /usersGuide</b> for more details on exactly what the benchmarks do."); - writer.WriteLine("</p><p>"); - writer.WriteLine("It is very easy for benchmark results to be wrong or misleading. You should read the guidance"); - writer.WriteLine("in the <b>MeasureIt /usersGuide</b> before making important decisions based on this data."); - writer.WriteLine("</p><p>"); - writer.WriteLine("To improve the stability of the measurements, a may be cloned several times"); - writer.WriteLine("and this cloned code is then run in a loop."); - writer.WriteLine("If the benchmark was cloned the 'scale' attribute represents the number of times"); - writer.WriteLine("it was cloned, and the count represents the number of times the cloned code was run in a loop"); - writer.WriteLine("before the measurement was made. The reported number divides by both"); - writer.WriteLine("of these values, so it represents a single instance of the operation being measured."); - writer.WriteLine("</p>"); - writer.WriteLine("<p>"); - writer.WriteLine("The benchmarks data can vary from run to run, so the benchmark is run several times and"); - writer.WriteLine("the statistics are displayed. If we assume a normal distribution, you can expect 68% of all measureuments"); - writer.WriteLine("to fall within 1 StdDev of the Mean. You can expect over 95% of all measurements"); - writer.WriteLine("to fall witin 2 StdDev of the Mean. Thus 2 StdDev is a good error bound."); - writer.WriteLine("Keep in mind, however that it is not uncommon for the statistics to be quite stable"); - writer.WriteLine("during a run and yet very widely across different runs. See the users guide for more."); - writer.WriteLine("</p>"); - writer.WriteLine("<p>"); - writer.WriteLine("Generally the mean is a better measurment if you use the number to compute an"); - writer.WriteLine("aggregate throughput for a large number of items. The median is a better"); - writer.WriteLine("guess if you want to best guess of a typical sample. The median is also"); - writer.WriteLine("more stable if the sample is noisy (eg has outliers)."); - writer.WriteLine("</p>"); - writer.WriteLine("<h3>Data collected</h3>"); - { - writer.WriteLine("<p>"); - writer.WriteLine(UnitsDescription); - writer.WriteLine("</p>"); - - dataSet.WriteReportTable(writer, Scale); - } - - writer.WriteLine("<p>"); - { - writer.WriteLine("<h2>Attributes of the machine used to collect the data</h2>"); - writer.WriteLine("<table border>"); - writer.WriteLine("<tr><th>Attribute</th><th>Value</th></tr>"); - foreach (string key in attributes.Keys) { - object valueObj = this[key]; - writer.Write("<tr>"); - writer.Write("<td>" + HttpUtility.HtmlEncode(key) + "</td>"); - - string valueStr = HttpUtility.HtmlEncode(valueObj.ToString()); - writer.Write("<td>" + valueStr + "</td>"); - writer.WriteLine("<tr>"); - } - writer.WriteLine("</table>"); - } - writer.WriteLine("</p>"); - - writer.WriteLine("</html>"); - writer.Close(); - } - static public void LaunchIE(string fileName) { - Process process = new Process(); - process.StartInfo = new ProcessStartInfo(fileName); - process.Start(); - } - - public float Scale = 1.0F; - public string UnitsDescription = "Scale in usec"; - - // TODO: probabably does not belong in this class. - public void CaptureCurrentMachineInfo(Assembly assemblyWithCode, bool skipMachineStats) { - this["Computer Name"] = Environment.MachineName; - if (!skipMachineStats) { - ////ComputerSpecs specs = new ComputerSpecs(); - ////this["Number of Processors"] = specs.NumberOfProcessors; - ////this["Processor Name "] = specs.ProcessorName; - ////this["Processor Mhz"] = specs.ProcessorClockSpeedMhz; - ////this["Memory MBytes"] = specs.MemoryMBytes; - ////this["L1 Cache KBytes"] = specs.L1KBytes; - ////this["L2 Cache KBytes"] = specs.L2KBytes; - ////this["Operating System"] = specs.OperatingSystem; - ////this["Operating System Version"] = specs.OperatingSystemVersion; - ////this["Stopwatch resolution (nsec)"] = (CodeTimer.ResolutionUsec * 1000.0).ToString("f3"); - } - - this["Machine Word Size (Bits)"] = (System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)) * 8).ToString(); - - this["CLR Version"] = Environment.Version.ToString(); - this["CLR Directory"] = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(); - - // Are we NGENed or JITTed? - if (IsNGenedCodeLoaded(assemblyWithCode)) - this["CompileType"] = "NGEN"; - else - this["CompileType"] = "JIT"; - - // Are we Appdomain Shared, or not? - MethodInfo currentMethod = Assembly.GetEntryAssembly().EntryPoint; - LoaderOptimizationAttribute loaderAttribute = (LoaderOptimizationAttribute)System.Attribute.GetCustomAttribute(currentMethod, typeof(LoaderOptimizationAttribute)); - if (loaderAttribute != null && loaderAttribute.Value == LoaderOptimization.MultiDomain) - this["CodeSharing"] = "AppDomainShared"; - else - this["CodeSharing"] = "AppDomainSpecific"; - - this["CodeOptimization"] = IsOptimized(assemblyWithCode) ? "Optimized" : "Unoptimized"; - } - - internal static bool IsOptimized(Assembly assembly) { - DebuggableAttribute debugAttribute = (DebuggableAttribute)System.Attribute.GetCustomAttribute(assembly, typeof(System.Diagnostics.DebuggableAttribute)); - if (debugAttribute != null && debugAttribute.IsJITOptimizerDisabled) - return false; - else - return true; - } - - static bool IsNGenedCodeLoaded(Assembly assembly) { - // This is a bit of a hack, basically I find the assemblies file name, then - // look for a module loaded called '<filename>.ni.<ext>'. It is not foolproof, - // but it more than good enough for most purposes. - string assemblyFileName = Path.GetFileName(assembly.ManifestModule.FullyQualifiedName); - string nativeImageExt = "ni" + Path.GetExtension(assemblyFileName); - string nativeImageSuffix = @"\" + Path.ChangeExtension(assemblyFileName, nativeImageExt); - - System.Diagnostics.Process myProcess = System.Diagnostics.Process.GetCurrentProcess(); - foreach (System.Diagnostics.ProcessModule module in myProcess.Modules) { - if (module.FileName.EndsWith(nativeImageSuffix, StringComparison.OrdinalIgnoreCase)) - return true; - } - return false; - } - - #region privates - Dictionary<string, object> attributes; - StatsCollection dataSet; - string category; - - #endregion - } - - /// <summary> - /// StatsCollection represents a collecton of named of samples (class - /// Stats) that have have been given string names. The data can be - /// looked up by name, but is also collection also remembers the order in - /// which the samples were added, and the names can be enumerated in that - /// order. - /// </summary> - internal class StatsCollection { - public StatsCollection() { - dict = new Dictionary<string, Stats>(); - order = new List<string>(); - } - - public Stats this[string key] { get { return dict[key]; } } - public bool ContainsKey(string key) { return dict.ContainsKey(key); } - public IEnumerable<string> Keys { get { return order; } } - public void Add(string key, Stats value) { - dict.Add(key, value); - order.Add(key); - } - public void WriteReportTable(TextWriter writer, float scale) { - writer.WriteLine("<table border>"); - writer.WriteLine("<tr><th>Name</th><th>Median</th><th>Mean</th><th>StdDev</th><th>Min</th><th>Max</th><th>Samples</th></tr>"); - - foreach (string key in this.Keys) { - Stats value = this[key]; - writer.Write("<tr>"); - writer.Write("<td>" + HttpUtility.HtmlEncode(key) + "</td>"); - writer.Write("<td>" + (value.Median / scale).ToString("f3") + "</td>"); - writer.Write("<td>" + (value.Mean / scale).ToString("f3") + "</td>"); - writer.Write("<td>" + (value.StandardDeviation / scale).ToString("f3") + "</td>"); - writer.Write("<td>" + (value.Minimum / scale).ToString("f3") + "</td>"); - writer.Write("<td>" + (value.Maximum / scale).ToString("f3") + "</td>"); - writer.Write("<td>" + value.Count + "</td>"); - writer.WriteLine("</tr>"); - } - writer.WriteLine("</table>"); - } - - #region privates - Dictionary<string, Stats> dict; - List<string> order; - #endregion - } -} - diff --git a/src/DotNetOpenAuth.Test/Performance/PerformanceTestUtilities.cs b/src/DotNetOpenAuth.Test/Performance/PerformanceTestUtilities.cs index 1077514..33a177a 100644 --- a/src/DotNetOpenAuth.Test/Performance/PerformanceTestUtilities.cs +++ b/src/DotNetOpenAuth.Test/Performance/PerformanceTestUtilities.cs @@ -1,20 +1,20 @@ -namespace DotNetOpenAuth.Test.Performance { +//----------------------------------------------------------------------- +// <copyright file="PerformanceTestUtilities.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.Test.Performance { using System; - using System.Collections.Generic; - using System.Linq; - using System.Text; - using log4net; - using NUnit.Framework; - using DotNetOpenAuth.Messaging; - using DotNetOpenAuth.OpenId.RelyingParty; - using System.Threading; using System.Diagnostics; + using System.Reflection; + using System.Threading; + using DotNetOpenAuth.OpenId.RelyingParty; + using NUnit.Framework; internal static class PerformanceTestUtilities { internal static Stats Baseline; - private static readonly StatsCollection data = new StatsCollection(); - static PerformanceTestUtilities() { Baseline = CollectBaseline(); TestUtilities.TestLogger.InfoFormat( @@ -22,8 +22,13 @@ Baseline.Median * 1000); } + internal static bool IsOptimized(Assembly assembly) { + DebuggableAttribute debugAttribute = (DebuggableAttribute)System.Attribute.GetCustomAttribute(assembly, typeof(System.Diagnostics.DebuggableAttribute)); + return debugAttribute == null || !debugAttribute.IsJITOptimizerDisabled; + } + internal static Stats Measure(Action action, float maximumAllowedUnitTime, int samples = 10, int iterations = 100, string name = null) { - if (!StatsLogger.IsOptimized(typeof(OpenIdRelyingParty).Assembly)) { + if (!IsOptimized(typeof(OpenIdRelyingParty).Assembly)) { Assert.Inconclusive("Unoptimized code."); } @@ -67,11 +72,11 @@ for (hits = 0; hits < hitsRequired; hits++) { float currentCpuUtilization = pc.NextValue(); if (currentCpuUtilization > maximumCpuUtilization) { - //Console.WriteLine("Miss: CPU at {0}% utilization", currentCpuUtilization); + ////Console.WriteLine("Miss: CPU at {0}% utilization", currentCpuUtilization); break; } - //Console.WriteLine("Hit: CPU at {0}% utilization", currentCpuUtilization); + ////Console.WriteLine("Hit: CPU at {0}% utilization", currentCpuUtilization); Thread.Sleep(samplingInterval); } @@ -88,18 +93,21 @@ private static Stats CollectBaseline() { using (new HighPerformance()) { - return new MultiSampleCodeTimer(10, 1000).Measure("MethodCalls: EmptyStaticFunction()", 10, delegate { - Class.EmptyStaticFunction(); - Class.EmptyStaticFunction(); - Class.EmptyStaticFunction(); - Class.EmptyStaticFunction(); - Class.EmptyStaticFunction(); - Class.EmptyStaticFunction(); - Class.EmptyStaticFunction(); - Class.EmptyStaticFunction(); - Class.EmptyStaticFunction(); - Class.EmptyStaticFunction(); - }); + return new MultiSampleCodeTimer(10, 1000).Measure( + "MethodCalls: EmptyStaticFunction()", + 10, + delegate { + Class.EmptyStaticFunction(); + Class.EmptyStaticFunction(); + Class.EmptyStaticFunction(); + Class.EmptyStaticFunction(); + Class.EmptyStaticFunction(); + Class.EmptyStaticFunction(); + Class.EmptyStaticFunction(); + Class.EmptyStaticFunction(); + Class.EmptyStaticFunction(); + Class.EmptyStaticFunction(); + }); } } @@ -109,55 +117,4 @@ } } } - - /// <summary> - /// Suppresses logging and forces the CPU into a high performance mode. - /// </summary> - internal class HighPerformance : IDisposable { - private readonly log4net.Core.Level originalLoggerThreshold; - private readonly PowerManagment.PowerSetting powerSetting; - private readonly ProcessPriorityClass originalProcessPriority; - -#pragma warning disable 0618 - /// <summary> - /// Initializes a new instance of the <see cref="HighPerformance"/> class. - /// </summary> - internal HighPerformance() { - if (!PerformanceTestUtilities.CoolOff()) { - Assert.Inconclusive("Timed out waiting for a quiet CPU in which to perform perf tests."); - } - - this.originalLoggerThreshold = LogManager.GetLoggerRepository().Threshold; - LogManager.GetLoggerRepository().Threshold = LogManager.GetLoggerRepository().LevelMap["OFF"]; - this.powerSetting = new PowerManagment.PowerSetting(PowerManagment.PowerProfiles.HighPerformance); - this.originalProcessPriority = Process.GetCurrentProcess().PriorityClass; - Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High; - Thread.CurrentThread.Priority = ThreadPriority.Highest; - HighCpu(); - } - - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> - public void Dispose() { - Thread.CurrentThread.Priority = ThreadPriority.Normal; - Process.GetCurrentProcess().PriorityClass = this.originalProcessPriority; - this.powerSetting.Dispose(); // restores original power setting. - LogManager.GetLoggerRepository().Threshold = this.originalLoggerThreshold; - } -#pragma warning restore 0618 - - /// <summary> - /// Runs the CPU in a tight loop to get it out of any low power state. - /// </summary> - private static void HighCpu() { - int dummy; - new MultiSampleCodeTimer(10, 1000).Measure("Loop 1K times", 1, delegate { - int k = 0; - while (k < 1000) - k++; // still in danger of being optimized. - dummy = k; // avoid optimization. - }); - } - } } diff --git a/src/DotNetOpenAuth.Test/Performance/PowerManagement.cs b/src/DotNetOpenAuth.Test/Performance/PowerManagement.cs index 66492f3..81c6e7a 100644 --- a/src/DotNetOpenAuth.Test/Performance/PowerManagement.cs +++ b/src/DotNetOpenAuth.Test/Performance/PowerManagement.cs @@ -6,23 +6,15 @@ namespace DotNetOpenAuth.Test.Performance { using System; - using System.Runtime.InteropServices; - using System.Diagnostics; using System.ComponentModel; + using System.Diagnostics; + using System.Runtime.InteropServices; /// <summary> /// PowerManagement allows you to access the funtionality of the Control Panel -> Power Options /// dialog in windows. (Currently we only use VISTA APIs). /// </summary> internal static class PowerManagment { - internal static class PowerProfiles { - internal static Guid HighPerformance = new Guid(0x8c5e7fda, 0xe8bf, 0x4a96, 0x9a, 0x85, 0xa6, 0xe2, 0x3a, 0x8c, 0x63, 0x5c); - - internal static Guid Balanced = new Guid(0x381b4222, 0xf694, 0x41f0, 0x96, 0x85, 0xff, 0x5b, 0xb2, 0x60, 0xdf, 0x2e); - - internal static Guid PowerSaver = new Guid(0xa1841308, 0x3541, 0x4fab, 0xbc, 0x81, 0xf7, 0x15, 0x56, 0xf2, 0x0b, 0x4a); - } - internal static unsafe Guid CurrentPolicy { get { Guid* retPolicy = null; @@ -33,7 +25,8 @@ namespace DotNetOpenAuth.Test.Performance { ret = *retPolicy; Marshal.FreeHGlobal((IntPtr)retPolicy); } - } catch (Exception) { } + } catch (Exception) { + } return ret; } @@ -46,6 +39,20 @@ namespace DotNetOpenAuth.Test.Performance { } } + [DllImport("powrprof.dll")] + private static unsafe extern int PowerGetActiveScheme(IntPtr reservedZero, ref Guid* policyGuidRet); + + [DllImport("powrprof.dll")] + private static extern int PowerSetActiveScheme(IntPtr reservedZero, ref Guid policyGuid); + + internal static class PowerProfiles { + internal static Guid HighPerformance = new Guid(0x8c5e7fda, 0xe8bf, 0x4a96, 0x9a, 0x85, 0xa6, 0xe2, 0x3a, 0x8c, 0x63, 0x5c); + + internal static Guid Balanced = new Guid(0x381b4222, 0xf694, 0x41f0, 0x96, 0x85, 0xff, 0x5b, 0xb2, 0x60, 0xdf, 0x2e); + + internal static Guid PowerSaver = new Guid(0xa1841308, 0x3541, 0x4fab, 0xbc, 0x81, 0xf7, 0x15, 0x56, 0xf2, 0x0b, 0x4a); + } + internal class PowerSetting : IDisposable { /// <summary> /// The power policy in effect when this instance was constructed. @@ -72,11 +79,5 @@ namespace DotNetOpenAuth.Test.Performance { } } } - - [DllImport("powrprof.dll")] - private static unsafe extern int PowerGetActiveScheme(IntPtr ReservedZero, ref Guid* policyGuidRet); - - [DllImport("powrprof.dll")] - private static extern int PowerSetActiveScheme(IntPtr ReservedZero, ref Guid policyGuid); } }
\ No newline at end of file |