Digamos que estoy implementando algo simple como buscar una lista / matriz ordenada. La función (en c #) sería similar a:
static int FindIndex(int[] sortedList, int i);
Podría implementar y probar esto en términos de funcionalidad, pero por razones obvias preferiría una búsqueda binaria sobre una búsqueda lineal o algo intencionalmente estúpido.
Entonces mi pregunta es: ¿Deberíamos intentar escribir pruebas que garanticen el rendimiento en términos de complejidad algorítmica y, de ser así, cómo?
He comenzado a hacer argumentos en ambos lados de la parte "debería" de esta pregunta, pero me gustaría ver qué dicen las personas sin mis argumentos para motivarlos.
En términos de "cómo", eso se vuelve muy interesante :) Podrías ver la parametrización del operador de comparación y tener una prueba cuyo operador de comparación cuenta comparaciones o algo así. Pero solo porque puedas no significa que debas ...
¿Alguien más ha considerado esto (probablemente)? Gracias.
fuente
Respuestas:
La complejidad algorítmica es una construcción teórica y, como tal, es mejor "probarla" con lápiz y papel. No puede ser útilmente probado mecánicamente.
El rendimiento absoluto se puede probar mecánicamente y puede hacer pruebas unitarias útiles. Si el rendimiento es importante, puede especificar un umbral: "esta consulta no debería tardar más de 50 ms en ejecutarse en 10 6 números y no más de 60 ms en 10 7 números". Para eso puedes construir una prueba unitaria.
Al usuario final no le importa si su algoritmo es lineal o logarítmico; les importa si su interfaz de usuario aún responde instantáneamente, incluso cuando tienen un año de datos en la aplicación.
fuente
Si bien no estoy seguro de si esta herramienta será particularmente útil para las pruebas unitarias, el artículo "Complejidad computacional empírica" de Goldsmith, Aiken y Wilkerson describe un método para instrumentar el código y observar su comportamiento dinámico en un conjunto de varias entradas de forma empírica. deriva su complejidad asintótica. El programa descrito en el documento es de código abierto y está disponible aquí .
¡Espero que esto ayude!
fuente
Lo principal es probarlo con big data y ver si tarda demasiado.
En mi experiencia de ajuste de rendimiento, como en este ejemplo , lo que sucede es que si algún algoritmo es (por ejemplo) O (n ^ 2) puede estar bien siempre y cuando el porcentaje de tiempo que lleva nunca salga al radar.
Sin embargo, cuando se le da un conjunto de datos de un tamaño que podría no verse pero una vez al año, la fracción del tiempo total absorbido por ese algoritmo puede volverse catastróficamente dominante.
Si puede hacer que eso suceda en las pruebas, eso es algo muy bueno, porque es sumamente fácil encontrar el problema, como si fuera un bucle infinito real.
fuente
No creo que lo que quieras hacer sea Prueba de unidad.
AFAIK, la prueba de la unidad es solo para asegurarse de que el código haga lo que debe hacer y no se centre en el rendimiento.
Existen otros tipos de herramientas y patrones para medir el rendimiento. Una de las que puedo recordar ahora es prueba de aceptación centrada en requisitos no funcionales.
Hay pocos otros como las pruebas de rendimiento. (que utiliza pruebas de estrés, pruebas de carga, etc.).
También podría usar algunas herramientas de estrés junto con una herramienta de compilación (ant, estudio de compilación automatizado) como parte de sus pasos de implementación (eso es lo que hago).
Entonces, la respuesta corta es no, no debe preocuparse por eso cuando la unidad prueba un código.
fuente
Pasar el comparador y hacer un seguimiento de la cantidad de veces que se llama funcionará para propósitos simples, como verificar que la cantidad de comparaciones al realizar una búsqueda en una entrada fija (digamos
new int[] { 1,2,3, ... , 1024 }
) permanezca por debajo de 10. Eso al menos deja en claro tus intenciones sobre cómo se supone que debe comportarse el algoritmo.No creo que las pruebas unitarias sean el camino correcto para verificar que su algoritmo sea O (log n); eso necesitaría mucha generación de datos aleatorios, algunos ajustes de curvas y probablemente estadísticas retorcidas para determinar si un grupo de puntos de datos se ajusta al tiempo de ejecución esperado. (Para este algoritmo probablemente sea factible, pero si comienzas a ordenar, etc., será difícil golpear repetidamente los peores escenarios).
fuente