¿Cómo puedo probar unitariamente optimizaciones de rendimiento en C#?


Estoy usando una versión optimizada del algoritmo de Levenshtein en algún código de búsqueda que estoy construyendo. Tengo pruebas unitarias funcionales para verificar que el algoritmo está devolviendo los resultados correctos, pero en este contexto el rendimiento del algoritmo también es muy importante.

Estoy buscando agregar algo de cobertura de prueba al proyecto para que si alguna modificación futura afecta a las optimizaciones, se muestren como pruebas fallidas, porque el algoritmo es determinista y se ejecuta en comparación con los datos de prueba conocidos, esto podría ser tan detallado como contar el número de instrucciones ejecutadas para un conjunto dado de entradas de prueba. En otras palabras, no estoy buscando medir el rendimiento del algoritmo usando temporizadores, estoy interesado en probar el comportamiento interno del algoritmo en lugar de solo la salida.

¿Alguna idea de cómo abordaría esto en C#/. NET 4?

EDIT: La razón por la que no quiero usar solo la hora del reloj de pared es que variará con la carga de la CPU y otros factores externos el control de la prueba. Eso podría llevar a pruebas que fallan cuando el servidor de compilación está bajo carga, por ejemplo. Será monitoreo de reloj de pared como parte del sistema desplegado.

EDIT 2: Piénsalo de esta manera... ¿cómo aplicaría rojo- > verde - > refactor cuando el rendimiento es un requisito crítico?

Author: Dylan Beattie, 2013-03-03

1 answers

Voy a responder la tercera parte de su pregunta, ya que he hecho esto con cierto éxito varias veces.

¿Cómo se aplica rojo->verde - > refactor cuando el rendimiento es un requisito crítico?

  1. Escriba pruebas de fijación para detectar regresiones, para lo que planea cambiar y otros métodos que pueden ralentizarse como resultado de sus cambios.
  2. Escriba una prueba de rendimiento que falle.
  3. Realice mejoras de rendimiento, ejecutando todas las pruebas frecuentemente.
  4. Actualice sus pruebas de fijación para fijar más de cerca el rendimiento.

Escribir pruebas de fijación

Cree un método auxiliar como este para cronometrar lo que desea anclar.

private TimeSpan Time(Action toTime)
{
    var timer = Stopwatch.StartNew();
    toTime();
    timer.Stop();
    return timer.Elapsed;
}

Luego escribe una prueba que afirme que tu método no toma tiempo:

[Test]
public void FooPerformance_Pin()
{
    Assert.That(Time(()=>fooer.Foo()), Is.LessThanOrEqualTo(TimeSpan.FromSeconds(0));
}

Cuando falle (con el tiempo real transcurrido en el mensaje de error), actualice el tiempo con algo un poco más que el tiempo real. Vuelve a ejecutarlo y pasará. Repita esto para otras funciones cuyo rendimiento podrías impactar con tus cambios, terminando con algo como esto.

[Test]
public void FooPerformance_Pin()
{
    Assert.That(Time(()=>fooer.Foo()), Is.LessThanOrEqualTo(TimeSpan.FromSeconds(0.8));
}
[Test]
public void BarPerformance_Pin()
{
    Assert.That(Time(()=>fooer.Bar()), Is.LessThanOrEqualTo(TimeSpan.FromSeconds(6));
}

Escribir una prueba de rendimiento fallida

Me gusta llamar a este tipo de prueba una "prueba de cebo". Es solo el primer paso de una prueba de fijación.

[Test]
public void FooPerformance_Bait()
{
    Assert.That(Time(()=>fooer.Foo()), Is.LessThanOrEqualTo(TimeSpan.FromSeconds(0));
}

Ahora, trabajar en mejoras de rendimiento. Ejecute todas las pruebas (fijación y cebo) después de cada mejora tentativa. Si tiene éxito, verá que el tiempo disminuye en la salida de falla de la prueba de cebo, y ninguno de sus pruebas de fijación fallarán.

Cuando esté satisfecho con las mejoras, actualice la prueba de fijación para el código que cambió y elimine la prueba de cebo.

¿Qué haces con estas pruebas ahora?

Lo menos preocupante es marcar estas pruebas con el atributo Explicit, y mantenerlas durante la próxima vez que desee comprobar el rendimiento.

En el lado opuesto del espectro de trabajo, creando un razonablemente bien controlado el subsistema en CI para ejecutar este tipo de pruebas es una muy buena manera de monitorear las regresiones de rendimiento. En mi experiencia hay mucha preocupación sobre ellos "fallando al azar debido a la carga de la CPU de otra cosa" que hay fallas reales. El éxito de este tipo de esfuerzo depende más de la cultura del equipo que de su capacidad para ejercer control sobre el entorno.

 32
Author: tallseth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-06 19:04:34