¿Se debe probar la complejidad algorítmica? ¿Si es así, cómo?

14

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.

SirPentor
fuente
@ steenhulthin - Dejaré que esto hierva a fuego lento aquí y verifique eso Nunca había estado allí.
SirPentor
Por cierto, buena pregunta. +1
Rafael Colucci

Respuestas:

13

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.

Crashworks
fuente
Este es mi instinto también. Pero lo que me hizo pensar en eso es cuando el rendimiento garantiza los marcos. Ejemplo: si recuerdo correctamente, el stl tiene algunas garantías sobre la complejidad algorítmica (podría estar desactivado aquí).
SirPentor
El hecho de que una biblioteca brinde algunas garantías no significa que tengan que ser comprobables por unidad.
svick
@Tobias Brick: Probar algo y definir algo son dos cosas diferentes.
DeadMG
Demostrar rendimiento es difícil. Implica muchos puntos de muestra para parámetros variables. Es más fácil cuando las funciones individuales son triviales, pero más allá de eso ... Su carga, su RAM, velocidad del bus frontal, CPU, número de núcleos, agresividad del compilador, grado de contaminación del registro afectarán el tiempo de ejecución de un determinado muestra.
Trabajo
3

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!

templatetypedef
fuente
0

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.

Mike Dunlavey
fuente
0

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.

De Wikipedia : No se puede esperar que las pruebas detecten todos los errores en el programa: es imposible evaluar cada ruta de ejecución en todos los programas, excepto en los más triviales. Lo mismo es cierto para las pruebas unitarias. Además, las pruebas unitarias por definición solo prueban la funcionalidad de las propias unidades. Por lo tanto, no detectará errores de integración o errores más amplios a nivel del sistema (como las funciones realizadas en varias unidades o áreas de prueba no funcionales como el rendimiento). Las pruebas unitarias deben realizarse junto con otras actividades de prueba de software. Al igual que todas las formas de prueba de software, las pruebas unitarias solo pueden mostrar la presencia de errores; No pueden mostrar la ausencia de errores.

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.

Rafael Colucci
fuente
0

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).

yatima2975
fuente