Medir el tiempo de ejecución del código

120

Quiero saber cuánto tiempo tarda un procedimiento / función / orden en finalizar, con fines de prueba.

Esto es lo que hice, pero mi método es incorrecto porque si la diferencia de segundos es 0, no puedo devolver los milisegundos transcurridos:

Observe que el valor de suspensión es de 500 ms, por lo que los segundos transcurridos son 0 y luego no pueden devolver milisegundos.

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

¿Alguien puede mostrarme una mejor manera de hacer esto? ¿Quizás con un TimeSpan?

La solución:

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
fuente
1
Puede ver mi respuesta a esta pregunta:> stackoverflow.com/a/16130243/1507182 Buena suerte
Obama
1
@Soner Si lo etiqueté con C # es porque el código C # es bienvenido para mí.
ElektroStudios
2
posible duplicado del tiempo de ejecución
Jesse
2
Además de las razones obvias para usar un cronómetro, nunca debe hacer cálculos matemáticos DateTime.Nowdebido a problemas con el horario de verano y la zona horaria. Lea la publicación de mi blog sobre este mismo tema
Matt Johnson-Pint

Respuestas:

234

Una mejor forma sería utilizar Cronómetro , en lugar de DateTimediferencias.

Clase de cronómetro - Microsoft Docs

Proporciona un conjunto de métodos y propiedades que puede utilizar para medir con precisión el tiempo transcurrido.

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
fuente
1
@ElektroHacker, de nada, es más fácil de usar y además es más preciso que DateTime :)
Habib
1
Consulte github.com/chai-deshpande/LogExec (un paquete NUGET también está disponible en nuget.org/packages/LogExec ). Esto hace exactamente lo mismo que mencionó @ soner-gonul, pero el uso está libre de desorden y oculta todo el código repetitivo. Muy útil cuando quieres usarlo con mucha frecuencia. También utiliza Common.Logging para que pueda integrarse con su proveedor de registro preferido.
Chai
1
@Habib, ¿podrías ayudarme a entender por qué es necesario Thread.sleep (500)? ¿No puedo hacerlo saltándome el sueño, eso lo haría menos eficiente?
Md Sifatul Islam
8
@ Md.SifatulIslam, no es necesario usarlo Thread.Sleep, solo está allí como un código de muestra para mostrar el retraso ... de hecho, debe evitar usar Thread.Sleepen cualquier parte de su código
Habib
59

Stopwatch mide el tiempo transcurrido.

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

Aquí hay un DEMO.

Soner Gönül
fuente
¿Se puede usar para el tiempo de ejecución de cada línea de código? por ejemplo: bindingSource.datasource = db.table; // ¿cuánto tarda?
vaheeds
2
@vaheeds Seguro. Simplemente comience esto Stopwatchen la parte superior de cada línea y deténgalo después de cada línea. Recuerde, debe usar también Stopwatch.Resetdespués de cada línea para calcular. Basado en su línea; echa un vistazo a ideone.com/DjR6ba
Soner Gönül
Hice un pequeño truco para sacar los milisegundos de la imagen. this way watch.Elapsed.ToString (). Split ('.') [0]
Doruk
2
@Doruk Sí, puede hacer eso o puede usar cadenas de formato de intervalo de tiempo personalizado como, stopwatch.Elapsed.ToString(@"d\.hh\:mm\:ss")que me parece una forma más limpia.
Soner Gönül
1
La mejor respuesta. ¡Gracias!
Tadej
48

Puede utilizar este contenedor de cronómetro:

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

Uso:

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

Salida:

Insert 10 records: 00:00:00.0617594

Para escenarios avanzados, puede usar BenchmarkDotNet o Benchmark.It o NBench

Alex Erygin
fuente
3
Gracias, la mejor respuesta hasta ahora
píxel
2
Gracias, estaba buscando tal de forma centralizada. También he hecho esta estrategia con ActionFilter.
ಅನಿಲ್
13

Si usa la clase Stopwatch, puede usar el método .StartNew () para restablecer el reloj a 0. Por lo tanto, no tiene que llamar a .Reset () seguido de .Start (). Podría ser útil.

oh dios no otro
fuente
4

Stopwatch está diseñado para este propósito y es una de las mejores formas de medir la ejecución del tiempo en .NET.

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

No utilice DateTimes para medir el tiempo de ejecución en .NET.

Sam
fuente
3

Si está buscando la cantidad de tiempo que el hilo asociado ha pasado ejecutando código dentro de la aplicación.
Puede usar ProcessThread.UserProcessorTimePropiedad que puede obtener en el System.Diagnosticsespacio de nombres.

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

Nota: si está utilizando varios hilos, puede calcular el tiempo de cada hilo individualmente y resumirlo para calcular la duración total.

Shailesh Prajapati
fuente
0

No pude ver una versión de vb.net de cómo se podría usar la clase de cronómetro, así que proporcioné un ejemplo a continuación.

        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)

Espero que esto ayude a cualquiera que haya llegado a esta pregunta buscando vb.net.

sawsine
fuente