2013-04-21 10 views
9

Я создаю проект для стеганографии для моего колледжа. Я закончил проект и сохранил несколько разных алгоритмов для скрытия данных в изображениях.Найти Время выполнения метода

Я хочу спросить, есть ли какой-либо способ в 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.

Нет многопоточности, поэтому это не проблема. Theres просто одна главная тема.

+0

Возможный дубликат [Время выполнения кода измерения] (https://stackoverflow.com/questions/16376191/measuring-code-execution-time) - Это на несколько дней старше, но [примечание] (https://meta.stackexchange.com/questions/10841/how-should-duplicate-questions-be-handled/). * Общее правило заключается в том, чтобы сохранить вопрос с наилучшим набором ответов и закрыть другой как дубликат . * " – ruffin

ответ

12

System.Environment.TickCount и класс System.Diagnostics.Stopwatch - это два, которые хорошо работают для более точного разрешения и простого использования.

Смотрите также:

  1. Is DateTime.Now the best way to measure a function’s performance?
  2. High resolution timer in .NET
  3. Environment.TickCount vs DateTime.Now
  4. What’s the best way to benchmark programs in Windows?
+3

Определенно используйте класс« Секундомер »для тестирования производительности. «TickCount» не особенно полезен для тестов. –

4

Вы можете использовать StopWatch класс:

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

Это полезный метод расширения для Секундомера:

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()); 
0

Вы можете объявить к вашему методу испытаний делегата и использовать один из следующих методов расширения для выполнить его 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}"); 

Таким образом, вы можете легко проверить ваши методы, если указанный метод не пустой метод, который приведет к искажению таймингов, поскольку делегат вызов будет быть сопоставимым с вашим вызовом метода. Оригинальная идея - блог here.

Для более глубокого анализа времени вызова профилировщик тоже очень полезен. Вы должны попытаться использовать их, чтобы иметь возможность диагностировать более сложные проблемы.

using System; 
using System.Globalization; 
using System.Diagnostics; 

namespace PerformanceTester 
{ 
    /// <summary> 
    /// Helper class to print out performance related data like number of runs, elapsed time and frequency 
    /// </summary> 
    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; 
      } 
     } 

     /// <summary> 
     /// Execute the given function and print the elapsed time to the console. 
     /// </summary> 
     /// <param name="func">Function that returns the number of iterations.</param> 
     /// <param name="format">Format string which can contain {runs} or {0},{time} or {1} and {frequency} or {2}.</param> 
     public static void Profile(this Func<int> 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); 
      } 
     } 

     /// <summary> 
     /// Execute the given function n-times and print the timing values (number of runs, elapsed time, call frequency) 
     /// to the console window. 
     /// </summary> 
     /// <param name="func">Function to call in a for loop.</param> 
     /// <param name="runs">Number of iterations.</param> 
     /// <param name="format">Format string which can contain {runs} or {0},{time} or {1} and {frequency} or {2}.</param> 
     public static void Profile(this Action func, int runs, string format) 
     { 
      Func<int> f =() => 
      { 
       for (int i = 0; i < runs; i++) 
       { 
        func(); 
       } 
       return runs; 
      }; 
      f.Profile(format); 
     } 

     /// <summary> 
     /// Call a function in a for loop n-times. The first function call will be measured independently to measure 
     /// first call effects. 
     /// </summary> 
     /// <param name="func">Function to call in a loop.</param> 
     /// <param name="runs">Number of iterations.</param> 
     /// <param name="formatFirst">Format string for first function call performance.</param> 
     /// <param name="formatOther">Format string for subsequent function call performance.</param> 
     /// <remarks> 
     /// The format string can contain {runs} or {0},{time} or {1} and {frequency} or {2}. 
     /// </remarks> 
     public static void ProfileWithFirst(this Action func, int runs, string formatFirst, string formatOther) 
     { 
      func.Profile(1, formatFirst); 
      func.Profile(runs - 1, formatOther); 
     } 
    } 
} 
0

Вы также можете использовать BenchmarkDotNet

Тогда вы:

1) Создайте проект консольного со ссылкой на код, который вы хотите проверить.

using BenchmarkDotNet.Running; 
using BenchmarkDotNet.Attributes; 
class Program 
{ 
    static void Main() 
    { 
     var summary = BenchmarkRunner.Run<YourBenchmarks>(); 
    } 
} 

public class YourBenchmarks 
{ 
    [Benchmark] 
    public object HideDataUsingAlgorithm() 
    { 
     return Namespace.hideDataUsingAlgorithm(); // call the code you want to benchmark here 
    } 
} 

2) Сборка и запуск без отладчика.

3) Откройте отчет, который находится в бен/выпуска/YourBenchmarks-report-stackoverflow.md

Отчет содержит медианы и STDDEV по умолчанию. BenchmarkDotNet заботится о разминки и запускает процесс несколько раз, чтобы дать точную статистику.

Пример отчета:

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

Для конфигурации читать docs.

Смежные вопросы