Pomiar czasu wykonania kodu

120

Chcę wiedzieć, ile czasu zajmuje zakończenie procedury / funkcji / zamówienia do celów testowych.

Oto, co zrobiłem, ale moja metoda jest nieprawidłowa, ponieważ jeśli różnica sekund wynosi 0, nie może zwrócić liczby milisekund, które upłynęły:

Zwróć uwagę, że wartość uśpienia wynosi 500 ms, więc upływających sekund wynosi 0, a następnie nie może zwrócić milisekund.

    Dim Execution_Start As System.DateTime = System.DateTime.Now
    Threading.Thread.Sleep(500)

    Dim Execution_End As System.DateTime = System.DateTime.Now
    MsgBox(String.Format("H:{0} M:{1} S:{2} MS:{3}", _
    DateDiff(DateInterval.Hour, Execution_Start, Execution_End), _
    DateDiff(DateInterval.Minute, Execution_Start, Execution_End), _
    DateDiff(DateInterval.Second, Execution_Start, Execution_End), _
    DateDiff(DateInterval.Second, Execution_Start, Execution_End) * 60))

Czy ktoś może mi pokazać lepszy sposób na zrobienie tego? Może z TimeSpan?

Rozwiązanie:

Dim Execution_Start As New Stopwatch
Execution_Start.Start()

Threading.Thread.Sleep(500)

MessageBox.Show("H:" & Execution_Start.Elapsed.Hours & vbNewLine & _
       "M:" & Execution_Start.Elapsed.Minutes & vbNewLine & _
       "S:" & Execution_Start.Elapsed.Seconds & vbNewLine & _
       "MS:" & Execution_Start.Elapsed.Milliseconds & vbNewLine, _
       "Code execution time", MessageBoxButtons.OK, MessageBoxIcon.Information)
ElektroStudios
źródło
1
Możesz zobaczyć moją odpowiedź na to pytanie:> stackoverflow.com/a/16130243/1507182 Powodzenia
Obama
1
@Soner Jeśli otagowałem go C #, to dlatego, że kod C # jest dla mnie mile widziany.
ElektroStudios
2
możliwy duplikat czasu wykonania metody Find
Jesse
2
Oprócz oczywistych powodów, dla których warto używać stopera, nigdy nie należy wykonywać żadnych działań matematycznych z DateTime.Nowpowodu problemów z czasem letnim i strefą czasową. Zapraszam do przeczytania mojego wpisu na blogu na ten temat
Matt Johnson-Pint

Odpowiedzi:

234

Lepszym sposobem byłoby użycie Stopera zamiast DateTimeróżnic.

Klasa stopera - Microsoft Docs

Zawiera zestaw metod i właściwości, których można użyć do dokładnego pomiaru czasu, który upłynął.

Stopwatch stopwatch = Stopwatch.StartNew(); //creates and start the instance of Stopwatch
//your sample code
System.Threading.Thread.Sleep(500);
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds);
Habib
źródło
1
@ElektroHacker, nie ma za co, jest łatwiejszy w użyciu, a do tego dokładniejszy niż DateTime :)
Habib
1
Odwiedź stronę github.com/chai-deshpande/LogExec (dostępny jest również pakiet NUGET nuget.org/packages/LogExec ). Robi dokładnie to samo, o czym wspomniał @ soner-gonul - ale użycie jest bezproblemowe i ukrywa cały kod standardowy. Bardzo pomocny, gdy chcesz go używać bardzo często. Używa również Common.Logging, dzięki czemu możesz zintegrować się z preferowanym dostawcą logowania.
Chai
1
@Habib, czy możesz mi pomóc zrozumieć, dlaczego Thread.sleep (500) jest konieczny? Nie mogę tego zrobić, pomijając sen, czy to zmniejszyłoby wydajność?
Md Sifatul Islam
8
@ Md.SifatulIslam, nie ma potrzeby go używać Thread.Sleep, jest tam tylko jako przykładowy kod pokazujący opóźnienie ... w rzeczywistości powinieneś unikać używania Thread.Sleepdowolnego miejsca w swoim kodzie
Habib
59

Stopwatch mierzy upływający czas.

// Create new stopwatch
Stopwatch stopwatch = new Stopwatch();

// Begin timing
stopwatch.Start();

Threading.Thread.Sleep(500)

// Stop timing
stopwatch.Stop();

Console.WriteLine("Time elapsed: {0}", stopwatch.Elapsed);

Oto plik DEMO.

Soner Gönül
źródło
czy może służyć do czasu wykonania każdego wiersza kodu? np: bindingSource.datasource = db.table; // ile to trwa?
vaheeds
2
@vaheeds Sure. Po prostu zacznij to Stopwatchna górze każdej linii i zatrzymaj po każdej linii. Pamiętaj, że Stopwatch.Resetaby obliczyć , musisz użyć również po każdej linii. Na podstawie twojej linii; spójrz na ideone.com/DjR6ba
Soner Gönül
Zrobiłem na tym małą sztuczkę, aby usunąć milisekundy z obrazu. this way watch.Elapsed.ToString (). Split ('.') [0]
Doruk
2
@Doruk Tak, można to zrobić albo użyć klienta Okres łańcuchów formatu jak stopwatch.Elapsed.ToString(@"d\.hh\:mm\:ss")co wydaje się czystszy sposób do mnie.
Soner Gönül
1
Najlepsza odpowiedź. Dzięki!
Tadej
48

Możesz użyć tego opakowania stopera:

public class Benchmark : IDisposable 
{
    private readonly Stopwatch timer = new Stopwatch();
    private readonly string benchmarkName;

    public Benchmark(string benchmarkName)
    {
        this.benchmarkName = benchmarkName;
        timer.Start();
    }

    public void Dispose() 
    {
        timer.Stop();
        Console.WriteLine($"{benchmarkName} {timer.Elapsed}");
    }
}

Stosowanie:

using (var bench = new Benchmark($"Insert {n} records:"))
{
    ... your code here
}

Wynik:

Insert 10 records: 00:00:00.0617594

W przypadku zaawansowanych scenariuszy możesz użyć BenchmarkDotNet lub Benchmark.It lub NBench

Alex Erygin
źródło
3
Dziękuję, najlepsza jak dotąd odpowiedź
piksel
2
Dzięki, szukałem takich w scentralizowany sposób. Zrobiłem tę strategię również z ActionFilter.
ಅನಿಲ್
13

Jeśli używasz klasy Stopwatch, możesz użyć metody .StartNew () , aby zresetować zegarek do wartości 0. Nie musisz więc wywoływać funkcji .Reset (), a następnie .Start (). Może się przydać.

ohgodnotanotherone
źródło
4

Stoper służy do tego celu i jest jednym z najlepszych sposobów pomiaru czasu wykonania w .NET.

var watch = System.Diagnostics.Stopwatch.StartNew();
/* the code that you want to measure comes here */
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;

Nie używaj DateTimes do mierzenia czasu wykonania w .NET.

Sam
źródło
3

Jeśli szukasz czasu, jaki skojarzony wątek spędził na uruchamianiu kodu wewnątrz aplikacji.
Możesz użyć ProcessThread.UserProcessorTimewłaściwości, którą możesz uzyskać w System.Diagnosticsprzestrzeni nazw.

TimeSpan startTime= Process.GetCurrentProcess().Threads[i].UserProcessorTime; // i being your thread number, make it 0 for main
//Write your function here
TimeSpan duration = Process.GetCurrentProcess().Threads[i].UserProcessorTime.Subtract(startTime);

Console.WriteLine($"Time caluclated by CurrentProcess method: {duration.TotalSeconds}"); // This syntax works only with C# 6.0 and above

Uwaga: Jeśli używasz wielu wątków, możesz obliczyć czas każdego wątku osobno i zsumować go, aby obliczyć całkowity czas trwania.

Shailesh Prajapati
źródło
0

Nie widziałem wersji vb.net, jak można używać klasy stopera, więc poniżej podałem przykład.

        Dim Stopwatch As New Stopwatch

        Stopwatch.Start()
                    ''// Test Code
        Stopwatch.Stop()
        Console.WriteLine(Stopwatch.Elapsed.ToString)

        Stopwatch.Restart()            
                   ''// Test Again

        Stopwatch.Stop()
        Console.WriteLine(Stopwatch.Elapsed.ToString)

Mam nadzieję, że pomoże to każdemu, kto przyszedł na to pytanie i szukał vb.net.

piła
źródło