Измерение времени выполнения кода

120

Я хочу знать, сколько времени требуется для завершения процедуры / функции / заказа, в целях тестирования.

Это то, что я сделал, но мой метод неправильный, потому что, если разница в секундах равна 0, я не могу вернуть прошедшие миллисекунды:

Обратите внимание, что значение сна составляет 500 мс, поэтому прошедшие секунды равны 0, тогда он не может возвращать миллисекунды.

    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))

Может кто-нибудь показать мне лучший способ сделать это? Может быть с собой TimeSpan?

Решение:

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
источник
1
Вы можете увидеть мой ответ на этот вопрос:> stackoverflow.com/a/16130243/1507182 Удачи
Обама
1
@Soner Если я пометил его C #, это потому, что код C # для меня приветствуется.
ElektroStudios
2
возможный дубликат Find Execution Time of a Method
Джесси
2
Помимо очевидных причин для использования секундомера, вы никогда не должны заниматься математикой DateTime.Nowиз-за проблем с переходом на летнее время и часовым поясом. Пожалуйста, прочтите мой блог по этой теме
Мэтт Джонсон-Пинт

Ответы:

234

Лучше использовать секундомер вместо DateTimeразличий.

Класс секундомера - Microsoft Docs

Предоставляет набор методов и свойств, которые можно использовать для точного измерения прошедшего времени.

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);
Хабиб
источник
1
@ElektroHacker, добро пожаловать, он проще в использовании, плюс он более точен, чем DateTime :)
Хабиб
1
Пожалуйста, обратитесь к github.com/chai-deshpande/LogExec (пакет NUGET также доступен nuget.org/packages/LogExec ). Это делает то же самое, что упоминал @ soner-gonul, но при этом не возникает беспорядка и скрывается весь шаблонный код. Очень полезно, если вы хотите использовать его очень часто. Он также использует Common.Logging, чтобы вы могли интегрироваться с предпочитаемым поставщиком журналов.
Chai
1
@Habib, не могли бы вы помочь мне понять, почему необходим Thread.sleep (500)? Не могу я сделать это без сна, это сделает его менее эффективным?
Md Sifatul Islam
8
@ Md.SifatulIslam, нет необходимости использовать Thread.Sleep, это просто как образец кода, чтобы показать задержку .... на самом деле вам следует избегать использования Thread.Sleepгде-либо в вашем коде
Хабиб
59

Stopwatch измеряет прошедшее время.

// 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);

Вот файл DEMO.

Сонер Генюль
источник
может ли он использоваться для времени выполнения каждой строки кода? например: bindingSource.datasource = db.table; // сколько времени это займет?
vaheeds
2
@vaheeds Конечно. Просто начните это Stopwatchповерх каждой строки и остановите ее после каждой строки. Помните, что вам нужно использовать также Stopwatch.Reseton после каждой строки для расчета. На основе вашей линии; взгляните ideone.com/DjR6ba
Soner Gönül
Я сделал небольшой трюк, чтобы получить миллисекунды вне изображения. таким образом watch.Elapsed.ToString (). Split ('.') [0]
Дорук
2
@Doruk Да, вы можете сделать это , или вы можете использовать Пользовательские TimeSpan формат строки , как , stopwatch.Elapsed.ToString(@"d\.hh\:mm\:ss")который кажется более чистым способом для меня.
Soner Gönül
1
Лучший ответ. Спасибо!
Тадей
48

Вы можете использовать эту обертку секундомера:

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

Использование:

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

Вывод:

Insert 10 records: 00:00:00.0617594

Для расширенных сценариев, вы можете использовать BenchmarkDotNet или Benchmark.It или Nbench

Алексей Ерыгин
источник
3
Спасибо, лучший ответ на данный момент
pixel
2
Спасибо, искал такие централизованно. Проделали эту стратегию и с ActionFilter.
ಅನಿಲ್
13

Если вы используете класс Stopwatch, вы можете использовать метод .StartNew () для сброса часов на 0. Таким образом, вам не нужно вызывать .Reset (), а затем .Start (). Может пригодиться.

ohgodnotanotherone
источник
4

Секундомер разработан для этой цели и является одним из лучших способов измерения времени выполнения в .NET.

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

Не используйте DateTimes для измерения времени выполнения в .NET.

Сэм
источник
3

Если вы ищете количество времени, которое связанный поток потратил на выполнение кода внутри приложения.
Вы можете использовать ProcessThread.UserProcessorTimeсвойство, которое вы можете получить в System.Diagnosticsпространстве имен.

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

Примечание. Если вы используете многопоточность, вы можете рассчитать время каждого потока отдельно и суммировать его для расчета общей продолжительности.

Шайлеш Праджапати
источник
0

Мне не удалось увидеть версию vb.net о том, как можно использовать класс секундомера, поэтому я привел пример ниже.

        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)

Надеюсь, это поможет любому, кто пришел к этому вопросу, ищущему vb.net.

sawsine
источник