visual unitarias studio stress software rendimiento pruebas para herramientas estres ejemplos carga c# .net performance testing

c# - unitarias - pruebas de stress software ejemplos



MediciĆ³n de tiempo exacto para pruebas de rendimiento (8)

Esta pregunta ya tiene una respuesta aquí:

¿Cuál es la forma más exacta de ver cuánto tiempo tardó en ingresar algo, por ejemplo, una llamada a un método?

Lo más fácil y rápido que supongo es esto:

DateTime start = DateTime.Now; { // Do some work } TimeSpan timeItTook = DateTime.Now - start;

¿Pero qué tan exacto es esto? ¿Hay mejores maneras?


Como han dicho otros, Stopwatch debería ser la herramienta adecuada para esto. Sin embargo, se pueden realizar algunas mejoras, vea este hilo específicamente: comparando muestras de código pequeño en C #, ¿se puede mejorar esta implementación? .

He visto algunos consejos útiles de Thomas Maierhofer aquí

Básicamente su código se ve así:

//prevent the JIT Compiler from optimizing Fkt calls away long seed = Environment.TickCount; //use the second Core/Processor for the test Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(2); //prevent "Normal" Processes from interrupting Threads Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High; //prevent "Normal" Threads from interrupting this thread Thread.CurrentThread.Priority = ThreadPriority.Highest; //warm up method(); var stopwatch = new Stopwatch() for (int i = 0; i < repetitions; i++) { stopwatch.Reset(); stopwatch.Start(); for (int j = 0; j < iterations; j++) method(); stopwatch.Stop(); print stopwatch.Elapsed.TotalMilliseconds; }

Otro enfoque es confiar en Process.TotalProcessTime para medir el tiempo que la CPU ha estado ocupada ejecutando el código / proceso , como se muestra aquí. Esto puede reflejar un escenario más real ya que ningún otro proceso afecta la medición. Hace algo como:

var start = Process.GetCurrentProcess().TotalProcessorTime; method(); var stop = Process.GetCurrentProcess().TotalProcessorTime; print (end - begin).TotalMilliseconds;

Una implementación desnuda y detallada de lo mismo se puede encontrar aquí.

Escribí una clase de ayuda para realizar ambas cosas de una manera fácil de usar:

public class Clock { interface IStopwatch { bool IsRunning { get; } TimeSpan Elapsed { get; } void Start(); void Stop(); void Reset(); } class TimeWatch : IStopwatch { Stopwatch stopwatch = new Stopwatch(); public TimeSpan Elapsed { get { return stopwatch.Elapsed; } } public bool IsRunning { get { return stopwatch.IsRunning; } } public TimeWatch() { if (!Stopwatch.IsHighResolution) throw new NotSupportedException("Your hardware doesn''t support high resolution counter"); //prevent the JIT Compiler from optimizing Fkt calls away long seed = Environment.TickCount; //use the second Core/Processor for the test Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(2); //prevent "Normal" Processes from interrupting Threads Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High; //prevent "Normal" Threads from interrupting this thread Thread.CurrentThread.Priority = ThreadPriority.Highest; } public void Start() { stopwatch.Start(); } public void Stop() { stopwatch.Stop(); } public void Reset() { stopwatch.Reset(); } } class CpuWatch : IStopwatch { TimeSpan startTime; TimeSpan endTime; bool isRunning; public TimeSpan Elapsed { get { if (IsRunning) throw new NotImplementedException("Getting elapsed span while watch is running is not implemented"); return endTime - startTime; } } public bool IsRunning { get { return isRunning; } } public void Start() { startTime = Process.GetCurrentProcess().TotalProcessorTime; isRunning = true; } public void Stop() { endTime = Process.GetCurrentProcess().TotalProcessorTime; isRunning = false; } public void Reset() { startTime = TimeSpan.Zero; endTime = TimeSpan.Zero; } } public static void BenchmarkTime(Action action, int iterations = 10000) { Benchmark<TimeWatch>(action, iterations); } static void Benchmark<T>(Action action, int iterations) where T : IStopwatch, new() { //clean Garbage GC.Collect(); //wait for the finalizer queue to empty GC.WaitForPendingFinalizers(); //clean Garbage GC.Collect(); //warm up action(); var stopwatch = new T(); var timings = new double[5]; for (int i = 0; i < timings.Length; i++) { stopwatch.Reset(); stopwatch.Start(); for (int j = 0; j < iterations; j++) action(); stopwatch.Stop(); timings[i] = stopwatch.Elapsed.TotalMilliseconds; print timings[i]; } print "normalized mean: " + timings.NormalizedMean().ToString(); } public static void BenchmarkCpu(Action action, int iterations = 10000) { Benchmark<CpuWatch>(action, iterations); } }

Solo llama

Clock.BenchmarkTime(() => { //code }, 10000000);

o

Clock.BenchmarkCpu(() => { //code }, 10000000);

La última parte del Clock es la parte difícil. Si desea mostrar el tiempo final, depende de usted elegir qué tipo de tiempo desea. Escribí un método de extensión NormalizedMean que le da la media de los tiempos de lectura para descartar el ruido. Quiero decir que calculo la desviación de cada tiempo de la media real, y luego descarto los valores que estaban más lejos (solo los más lentos) de la media de la desviación (llamada desviación absoluta; tenga en cuenta que no es la desviación estándar que se escucha a menudo) , y finalmente devuelve la media de los valores restantes. Esto significa, por ejemplo, si los valores cronometrados son { 1, 2, 3, 2, 100 } (en ms o lo que sea), descarta 100 y devuelve la media de { 1, 2, 3, 2 } que es 2 . O si los tiempos son { 240, 220, 200, 220, 220, 270 } , descarta 270 , y devuelve la media de { 240, 220, 200, 220, 220 } que es 220 .

public static double NormalizedMean(this ICollection<double> values) { if (values.Count == 0) return double.NaN; var deviations = values.Deviations().ToArray(); var meanDeviation = deviations.Sum(t => Math.Abs(t.Item2)) / values.Count; return deviations.Where(t => t.Item2 > 0 || Math.Abs(t.Item2) <= meanDeviation).Average(t => t.Item1); } public static IEnumerable<Tuple<double, double>> Deviations(this ICollection<double> values) { if (values.Count == 0) yield break; var avg = values.Average(); foreach (var d in values) yield return Tuple.Create(d, avg - d); }


Como han dicho otros, el Stopwatch es una buena clase para usar aquí. Puedes envolverlo en un método útil:

public static TimeSpan Time(Action action) { Stopwatch stopwatch = Stopwatch.StartNew(); action(); stopwatch.Stop(); return stopwatch.Elapsed; }

(Tenga en cuenta el uso de Stopwatch.StartNew() . Prefiero esto a crear un cronómetro y luego llamar a Start() en términos de simplicidad.) Obviamente esto incurre en el éxito de invocar a un delegado, pero en la gran mayoría de los casos que ganaron " ser relevante Luego escribirías:

TimeSpan time = StopwatchUtil.Time(() => { // Do some work });

Incluso podría crear una interfaz de ITimer para esto, con implementaciones de StopwatchTimer, CpuTimer StopwatchTimer, etc., donde esté disponible.


El cronómetro está bien, pero repita el trabajo 10 ^ 6 veces, luego divídalo por 10 ^ 6. Obtendrá mucha más precisión.


Estoy usando esto:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(myUrl); System.Diagnostics.Stopwatch timer = new Stopwatch(); timer.Start(); HttpWebResponse response = (HttpWebResponse)request.GetResponse(); statusCode = response.StatusCode.ToString(); response.Close(); timer.Stop();

De mi blog: C # Medición de tiempo para pruebas de rendimiento (no en inglés)


Sí, hay alguna función en el kernel de Windows

[System.Runtime.InteropServices.DllImport("KERNEL32")] private static extern bool QueryPerformanceCounter(ref long lpPerformanceCount); [System.Runtime.InteropServices.DllImport("KERNEL32")] private static extern bool QueryPerformanceFrequency(ref long lpFrequency); public static float CurrentSecond { get { long current = 0; QueryPerformanceCounter(ref current); long frequency = 0; QueryPerformanceFrequency(ref frequency); return (float) current / (float) frequency; } }


System.Diagnostics.Stopwatch está diseñado para esta tarea.


Una mejor manera es usar la clase Cronómetro:

using System.Diagnostics; // ... Stopwatch sw = new Stopwatch(); sw.Start(); // ... sw.Stop(); Console.WriteLine("Elapsed={0}",sw.Elapsed);