tiempo de ejecución medida en C #
-
29-09-2019 - |
Pregunta
Quiero medir la ejecución de una pieza de código y me pregunto cuál es el mejor método para hacer esto es?
Opción 1:
DateTime StartTime = DateTime.Now;
//Code
TimeSpan ts = DateTime.Now.Subtract(StartTime);
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds / 10);
Console.WriteLine(elapsedTime, "RunTime");
Opción 2: usando System.Diagnostics;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
//Code
stopWatch.Stop();
// Get the elapsed time as a TimeSpan value.
TimeSpan ts = stopWatch.Elapsed;
// Format and display the TimeSpan value.
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds / 10);
Console.WriteLine(elapsedTime, "RunTime");
Esto no es simplemente para la evaluación comparativa, es en realidad parte de la aplicación. El tiempo de la función tarda en ejecutar son datos relevantes. Sin embargo, no tiene por qué ser atómica o hiper-precisa.
¿Qué opción es mejor para el código de producción, o hace cualquier otro uso algo diferente y tal vez mejor?
Solución
La clase Stopwatch
está diseñado específicamente para medir el tiempo transcurrido y puede (si está disponible en su hardware) proporcionar una buena granularidad / exactitud utilizando un temporizador de hardware de alta frecuencia subyacente. Así que esto parece la mejor opción.
El IsHighResolution propiedad se puede utilizar para determinar si la alta resolución de tiempo está disponible. Por la documentación, que ofrece esta clase un envoltorio en la 'mejor disponible' API de Win32 para la sincronización exacta:
Específicamente, el campo
Frequency
y métodoGetTimestamp
se puede utilizar en lugar de la API de Win32 no administradoQueryPerformanceFrequency
yQueryPerformanceCounter
.
Hay antecedentes detallados sobre los API de Win32 [aquí] y en la documentación de MSDN vinculados 2 .
de alta resolución del temporizador
Un contador es un término general utilizado en programación para referirse a una aumentando la variable. algunos sistemas incluir un rendimiento de alta resolución contador que proporciona alta resolución transcurridos veces.
Si un rendimiento de alta resolución contador existe en el sistema, puede utilizar el QueryPerformanceFrequency funcionar para expresar la frecuencia, en recuentos por segundo. El valor de la recuento depende del procesador. En algunos procesadores, por ejemplo, el recuento podría ser la velocidad del ciclo de la reloj del procesador.
El QueryPerformanceCounter función recupera el valor actual de la de alta resolución de contador de rendimiento. Al llamar a esta función en el principio y final de una sección de código, una aplicación utiliza esencialmente el contador como una alta resolución Temporizador. Por ejemplo, supongamos que QueryPerformanceFrequency indica que la frecuencia de la contador de rendimiento de alta resolución está 50.000 recuentos por segundo. Si el las llamadas de solicitud QueryPerformanceCounter inmediatamente antes e inmediatamente después de la sección de código a ser programado, el valores de contador pueden ser 1500 recuentos y 3500 recuentos, respectivamente. Estas indicarían que los valores .04 segundos (2000 unidades) transcurrido mientras que el código ejecutado.
Otros consejos
No se trata sólo de que StopWatch
es más preciso, pero también que DateTime.Now
dará resultados incorrectos en algunas circunstancias.
Tenga en cuenta lo que ocurre durante un horario de verano de conmutación, por ejemplo - el uso de DateTime.Now
realmente puede dar un negativa Respuesta ??p>
Me suelen utilizar StopWatch
para este tipo de situación.
A partir de la página MSDN :
Cronómetro
Proporciona un conjunto de métodos y propiedades que se pueden utilizar para medir con precisión el tiempo transcurrido.
En el siguiente post lo uso para comparar el tiempo de ejecución de LINQ vs PLINQ:
Ni perjudicará el rendimiento, ya que se dice que no es tan crítica. Cronómetro parece más apropiado - sólo está restando tiempo al tiempo y no uno de fecha de otro. Fecha asunto lleva un poco más de memoria y CPU vez de tratar. También hay maneras de hacer el código más limpio, en caso de que planea volver a utilizarlo en varios lugares. La sobrecarga using
viene a la mente. Voy a buscar un ejemplo. Ok, código robado de:
http://stevesmithblog.com/blog/great : utiliza-de-usando-declaración-en-c /
public class ConsoleAutoStopWatch : IDisposable
{
private readonly Stopwatch _stopWatch;
public ConsoleAutoStopWatch()
{
_stopWatch = new Stopwatch();
_stopWatch.Start();
}
public void Dispose()
{
_stopWatch.Stop();
TimeSpan ts = _stopWatch.Elapsed;
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds / 10);
Console.WriteLine(elapsedTime, "RunTime");
}
}
private static void UsingStopWatchUsage()
{
Console.WriteLine("ConsoleAutoStopWatch Used: ");
using (new ConsoleAutoStopWatch())
{
Thread.Sleep(3000);
}
}
Tanto probable que se ajuste a sus necesidades bien, pero yo diría que el uso StopWatch
. ¿Por qué? Causa que está destinado para la tarea que está haciendo.
Tienes una clase que está construido para devolver la fecha / hora actual, que como es el caso puede ser utilizado para cosas de tiempo, y usted tiene una clase diseñada específicamente para las cosas de tiempo.
En este caso, sólo existen realmente las diferencias si necesita una precisión de milisegundos (en cuyo caso StopWatch
es más preciso), sino como un principio general, si existe una herramienta específica para la tarea que está buscando, entonces es mejor uno a uso.
Tengo un poco de clase para hacer este tipo de cosas ad hoc. Se utiliza la clase cronómetro - c # micro perfomance de pruebas .
por ejemplo.
var tester = new PerformanceTester(() => SomeMethod());
tester.MeasureExecTime(1000);
Console.Writeline(string.Format("Executed in {0} milliseconds", tester.AverageTime.TotalMilliseconds));
El uso por debajo de código
DateTime dExecutionTime;
dExecutionTime = DateTime.Now;
TimeSpan span = DateTime.Now.Subtract(dExecutionTime);
lblExecutinTime.Text = "total time taken " + Math.Round(span.TotalMinutes,2) + " minutes . >>---> " + DateTime.Now.ToShortTimeString();
Tomé respuesta de Hamish lo simplificó y lo hizo un poco más general en caso tienes que entrar a algún otro lugar:
public class AutoStopWatch : Stopwatch, IDisposable {
public AutoStopWatch() {
Start();
}
public virtual void Dispose() {
Stop();
}
}
public class AutoStopWatchConsole : AutoStopWatch {
private readonly string prefix;
public AutoStopWatchConsole(string prefix = "") {
this.prefix = prefix;
}
public override void Dispose() {
base.Dispose();
string format = Elapsed.Days > 0 ? "{0} days " : "";
format += "{1:00}:{2:00}:{3:00}.{4:00}";
Console.WriteLine(prefix + " " + format.Format(Elapsed.Days, Elapsed.Hours, Elapsed.Minutes, Elapsed.Seconds, Elapsed.Milliseconds / 10));
}
}
private static void Usage() {
Console.WriteLine("AutoStopWatch Used: ");
using (var sw = new AutoStopWatch()) {
Thread.Sleep(3000);
Console.WriteLine(sw.Elapsed.ToString("h'h 'm'm 's's'"));
}
Console.WriteLine("AutoStopWatchConsole Used: ");
using (var sw = new AutoStopWatchConsole()) {
Thread.Sleep(3000);
}
}