2013-04-21 71 views
9

Tworzę projekt Image Steganography dla mojej uczelni. Skończyłem projekt i zachowałem kilka różnych algorytmów ukrywania danych w obrazach.Znajdź Czas wykonania metody

Chciałbym zapytać, czy jest jakiś sposób w C#, dzięki któremu mogę znaleźć czas wykonania/działania między dwoma punktami w programie. Na przykład

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

chcę to zrobić, aby pokazać różnicę między zwykłą (mniej czasochłonne) i bardziej wydajne, ale czasochłonnych algorytmów (stosując te same dane i sam obraz). Mam około 10 różnych algorytmów dla obrazów Color i GrayScale.

Nie ma wielowątkowości, więc nie będzie problemu. To tylko jeden główny wątek.

+0

Możliwy duplikat [Czas wykonania kodu pomiaru] (https://stackoverflow.com/questions/16376191/measuring-code-execution-time) - Jest to kilka dni starszy, ale [uwaga] (https://meta.stackexchange.com/questions/10841/how-should-duplicate-questions-be-handled/), "* Ogólna zasada polega na zachowaniu pytania z najlepszym zbiorem odpowiedzi, a zamknięcie drugiego jako duplikatu . * " – ruffin

Odpowiedz

12
+3

Zdecydowanie użyj klasy' Stopwatch' do testowania wydajności. 'TickCount' nie jest szczególnie przydatny do testów porównawczych. –

4

Można użyć StopWatch Klasa:

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

Jest to użyteczna metoda rozszerzenie dla Stoper:

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"; 
    } 
} 

używać go tak:

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

Można zadeklarować do metody badawczej delegata i użyć jednej z następujących metod rozszerzenie do wykonaj to N razy. W oparciu o przekazany ciąg formatu Ci drukowanej do konsoli:

  • najpierw wywołać czas
  • Upływający czas
  • częstotliwość połączeń

które są użyteczne wartości. Metody rozszerzenia używają Stoper, aby uzyskać najwyższą dokładność.

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

Aby sprawdzić także skutki startowe można użyć

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

W ten sposób można łatwo sprawdzić swoje metody, jeśli omawiana metoda nie jest pustym metoda, która mogłaby naruszyć czasy, ponieważ wezwanie delegat będzie być porównywalne do wywołania metody. Oryginalnym pomysłem jest blog here.

Dla głębszej analizy czasu połączenia bardzo przydatny jest profiler. Powinieneś spróbować również ich użyć, aby móc zdiagnozować trudniejsze problemy.

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

Można również użyć BenchmarkDotNet

Następnie zrobić:

1) Utwórz projekt konsoli z odniesieniem do kodu, który chcesz przetestować.

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) Wbuduj i uruchom bez debuggera.

3) Otwórz raport, który jest w bin/release/YourBenchmarks-report-stackoverflow.md

Raport zawiera mediana i OdchStd domyślnie. BenchmarkDotNet zajmuje rozgrzewki i uruchamia proces kilka razy, aby podać dokładne statystyki.

Przykładowy raport:

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

Dla konfiguracji przeczytać docs.

Powiązane problemy