¿Es DateTime.Now la mejor manera de medir el rendimiento de una función? [cerrado]
Necesito encontrar un cuello de botella y necesito medir el tiempo con la mayor precisión posible.
¿Es el siguiente fragmento de código la mejor manera de medir el rendimiento?
DateTime startTime = DateTime.Now;
// Some execution process
DateTime endTime = DateTime.Now;
TimeSpan totalTimeTaken = endTime.Subtract(startTime);
No, no es. Utilice el cronómetro (en System.Diagnostics
)
Stopwatch sw = Stopwatch.StartNew();
PerformWork();
sw.Stop();
Console.WriteLine("Time taken: {0}ms", sw.Elapsed.TotalMilliseconds);
El cronómetro comprueba automáticamente la existencia de temporizadores de alta precisión.
Vale la pena mencionar que DateTime.Now
a menudo es un poco más lento DateTime.UtcNow
debido al trabajo que hay que hacer con las zonas horarias, el horario de verano y demás.
DateTime.UtcNow normalmente tiene una resolución de 15 ms. Consulte la publicación del blog de John Chapman sobre DateTime.Now
precisión para obtener un excelente resumen.
Trivia interesante: el cronómetro vuelve a funcionar DateTime.UtcNow
si su hardware no admite un contador de alta frecuencia. Puede comprobar si Stopwatch utiliza hardware para lograr una alta precisión observando el campo estático Stopwatch.IsHighResolution .
Si quieres algo rápido y sucio, te sugiero que utilices el cronómetro para obtener un mayor grado de precisión.
Stopwatch sw = new Stopwatch();
sw.Start();
// Do Work
sw.Stop();
Console.WriteLine("Elapsed time: {0}", sw.Elapsed.TotalMilliseconds);
Alternativamente, si necesita algo un poco más sofisticado, probablemente debería considerar el uso de un generador de perfiles de terceros como ANTS .
Este artículo dice que, en primer lugar , debe comparar tres alternativas Stopwatch
, DateTime.Now
Y.DateTime.UtcNow
También muestra que en algunos casos (cuando el contador de rendimiento no existe) Stopwatch usa DateTime.UtcNow + algún procesamiento adicional. Por eso es obvio que en ese caso DateTime.UtcNow es la mejor opción (porque otros lo usan + algo de procesamiento)
Sin embargo, resulta que el contador casi siempre existe; consulte la Explicación sobre el contador de rendimiento de alta resolución y su existencia en relación con .NET Stopwatch. .
A continuación se muestra un gráfico de rendimiento. Observe el bajo costo de rendimiento que tiene UtcNow en comparación con las alternativas:
El eje X es el tamaño de los datos de la muestra y el eje Y es el tiempo relativo del ejemplo.
Una cosa Stopwatch
que es mejor es que proporciona mediciones de tiempo de mayor resolución. Otra es su naturaleza más OO. Sin embargo, crear un contenedor OO UtcNow
no puede ser difícil.
Es útil insertar su código de evaluación comparativa en una clase/método de utilidad. StopWatch
No es necesario que la clase Disposed
tenga Stopped
un error. Entonces, el código más simple para cronometrar alguna acción es
public partial class With
{
public static long Benchmark(Action action)
{
var stopwatch = Stopwatch.StartNew();
action();
stopwatch.Stop();
return stopwatch.ElapsedMilliseconds;
}
}
Código de llamada de muestra
public void Execute(Action action)
{
var time = With.Benchmark(action);
log.DebugFormat(“Did action in {0} ms.”, time);
}
Aquí está la versión del método de extensión.
public static class Extensions
{
public static long Benchmark(this Action action)
{
return With.Benchmark(action);
}
}
Y código de llamada de muestra
public void Execute(Action action)
{
var time = action.Benchmark()
log.DebugFormat(“Did action in {0} ms.”, time);
}