查找方法的执行时间

我正在为我的大学制作一个图像隐写项目。 我已完成项目并保留了几种不同的算法来隐藏图像中的数据。

我想问的是,在C#中有什么方法可以通过它找到程序中两点之间的执行/运行时间。 例如

//Some Code //Code to start recording the time. hideDataUsingAlgorithm(); //Code to stop recording and get the time of execution of the above function. 

我想这样做是为了显示简单(耗时较少)和更高效但耗时的算法(使用相同的数据和相同的图像)之间的区别。 我有大约10种不同的Color和GrayScale图像算法。

没有multithreading因此不会成为问题。 Theres只是一个主线程。

System.Environment.TickCount和System.Diagnostics.Stopwatch类是两个适用于更精细的分辨率和直接使用的类。

也可以看看:

  1. DateTime.Now是测量函数性能的最佳方法吗?
  2. .NET中的高分辨率计时器
  3. Environment.TickCount与DateTime.Now
  4. 在Windows中对程序进行基准测试的最佳方法是什么?

这是一个有用的秒表扩展方法:

 public static class StopwatchExt { public static string GetTimeString(this Stopwatch stopwatch, int numberofDigits = 1) { double time = stopwatch.ElapsedTicks / (double)Stopwatch.Frequency; if (time > 1) return Math.Round(time, numberofDigits) + " s"; if (time > 1e-3) return Math.Round(1e3 * time, numberofDigits) + " ms"; if (time > 1e-6) return Math.Round(1e6 * time, numberofDigits) + " µs"; if (time > 1e-9) return Math.Round(1e9 * time, numberofDigits) + " ns"; return stopwatch.ElapsedTicks + " ticks"; } } 

像这样用它:

 Stopwatch stopwatch = Stopwatch.StartNew(); //Call your method here stopwatch.Stop(); Console.WriteLine(stopwatch.GetTimeString()); 

您可以使用StopWatch类:

 var timer = System.Diagnostics.StopWatch.StartNew(); hideDataUsingAlgorithm(); timer.Stop(); var elapsed = timer.ElapsedMilliseconds; 

您可以向您的测试方法声明一个委托,并使用以下扩展方法之一执行N次。 基于传递的格式字符串,您将打印到控制台:

  • 第一次通话时间
  • 经过的时间
  • 通话频率

这些都是有用的价值。 扩展方法使用秒表来获得最高精度。

 Action acc = hideDataUsingAlgorithm; acc.Profile(100*1000, "Method did run {runs} times in {time}s, Frequency: {frequency}"); 

还要检查您可以使用的启动效果

 acc.ProfileFirst(100*1000, "First call {0}s", "Method did run {runs} times in {time}s, Frequency: {frequency}"); 

这样,如果所讨论的方法不是一个会导致时序失真的空方法,则可以轻松检查方法,因为委托调用与您的方法调用相当。 最初的想法是在这里写博客。

对于更深入的呼叫时间分析,分析器也非常有用。 您应该尝试使用这些以便能够诊断棘手的问题。

 using System; using System.Globalization; using System.Diagnostics; namespace PerformanceTester { ///  /// Helper class to print out performance related data like number of runs, elapsed time and frequency ///  public static class Extension { static NumberFormatInfo myNumberFormat; static NumberFormatInfo NumberFormat { get { if (myNumberFormat == null) { var local = new CultureInfo("en-us", false).NumberFormat; local.NumberGroupSeparator = " "; // set space as thousand separator myNumberFormat = local; // make a thread safe assignment with a fully initialized variable } return myNumberFormat; } } ///  /// Execute the given function and print the elapsed time to the console. ///  /// Function that returns the number of iterations. /// Format string which can contain {runs} or {0},{time} or {1} and {frequency} or {2}. public static void Profile(this Func func, string format) { Stopwatch watch = Stopwatch.StartNew(); int runs = func(); // Execute function and get number of iterations back watch.Stop(); string replacedFormat = format.Replace("{runs}", "{3}") .Replace("{time}", "{4}") .Replace("{frequency}", "{5}"); // get elapsed time back float sec = watch.ElapsedMilliseconds / 1000.0f; float frequency = runs / sec; // calculate frequency of the operation in question try { Console.WriteLine(replacedFormat, runs, // {0} is the number of runs sec, // {1} is the elapsed time as float frequency, // {2} is the call frequency as float runs.ToString("N0", NumberFormat), // Expanded token {runs} is formatted with thousand separators sec.ToString("F2", NumberFormat), // expanded token {time} is formatted as float in seconds with two digits precision frequency.ToString("N0", NumberFormat)); // expanded token {frequency} is formatted as float with thousands separators } catch (FormatException ex) { throw new FormatException( String.Format("The input string format string did contain not an expected token like "+ "{{runs}}/{{0}}, {{time}}/{{1}} or {{frequency}}/{{2}} or the format string " + "itself was invalid: \"{0}\"", format), ex); } } ///  /// Execute the given function n-times and print the timing values (number of runs, elapsed time, call frequency) /// to the console window. ///  /// Function to call in a for loop. /// Number of iterations. /// Format string which can contain {runs} or {0},{time} or {1} and {frequency} or {2}. public static void Profile(this Action func, int runs, string format) { Func f = () => { for (int i = 0; i < runs; i++) { func(); } return runs; }; f.Profile(format); } ///  /// Call a function in a for loop n-times. The first function call will be measured independently to measure /// first call effects. ///  /// Function to call in a loop. /// Number of iterations. /// Format string for first function call performance. /// Format string for subsequent function call performance. ///  /// The format string can contain {runs} or {0},{time} or {1} and {frequency} or {2}. ///  public static void ProfileWithFirst(this Action func, int runs, string formatFirst, string formatOther) { func.Profile(1, formatFirst); func.Profile(runs - 1, formatOther); } } } 

您也可以使用BenchmarkDotNet

然后你做:

1)创建一个控制台项目,其中引用了您要测试的代码。

 using BenchmarkDotNet.Running; using BenchmarkDotNet.Attributes; class Program { static void Main() { var summary = BenchmarkRunner.Run(); } } public class YourBenchmarks { [Benchmark] public object HideDataUsingAlgorithm() { return Namespace.hideDataUsingAlgorithm(); // call the code you want to benchmark here } } 

2)内置发布并在没有调试器的情况下运行。

3)打开bin / release / YourBenchmarks-report-stackoverflow.md中的报告

该报告默认包含Median和StdDev。 BenchmarkDotNet负责预热并多次启动该过程以提供准确的统计数据。

样本报告:

  Method | Median | StdDev | ----------------------- |------------ |---------- | HideDataUsingAlgorithm | 252.4869 ns | 8.0261 ns | 

有关配置,请阅读文档 。