\chapter{Introducción}
En los inicios de la informática, el hardware estaba muy limitado y la optimización del software, tanto en espacio como en tiempo, era crucial.
A veces la optimización iba incluso en detrimento de la inteligibilidad del código y, en consecuencia, de su mantenibilidad.

La despreocupación del diseño y la falta de previsión de años anteriores hizo que el coste de desarrollo y mantenimiento de software fuera excesivo.
La ingeniería del software es una disciplina que surgió en respuesta a estos problemas,
aglutina metodologías, técnicas y herramientas para gestionar la complejidad del desarrollo y mantenimiento de productos informáticos.
Actualmente, la situación es casi inversa a los inicios, ya que el desarrollo se centra en el diseño del software obviando la optimización de los sistemas.
Esto es un problema en ciertos ámbitos donde todavía es necesario optimizar recursos al límite
(sistemas en tiempo real, programación multimedia,...).

Volviendo al tema de la Ingeniería del Software, dos tendencias han tenido un notable éxito en los últimos años: las metodologías ágiles y {\it open source}.

Las metodologías ágiles pretenden aligerar la sobrecarga que las metodologías clásicas añadían al proceso de desarrollo.
Una de las metodologías ágiles más extendida es el {\it Extreme Programming}.
El {\it Extreme Programming} fue creado con el objetivo de entregar al cliente una solución funcional lo antes posible.
Para ello, se llevan a cabo un conjunto de práticas como refactorización del código ({\it Refactoring}), testeo del código después de cada cambio ({\it Test Driven Development}), programación por parejas, desarrollo iterativo, simplicidad en la programación y contacto contínuo con el cliente, entre otras.
Las dos primeras prácticas mencionadas son las que mayor relación tienen con nuestro proyecto.
El {\it Refactoring}, es una técnica para reestructurar un código fuente, alterando su estructura interna sin cambiar su comportamiento externo,
mientras que el {\it Test Driven Development} se basa en el testeo unitario contínuo para corroborar que la funcionalidad del sistema es correcta.
La combinación adecuada de ambas prácticas permite un diseño claro y flexible, lo que favorece al mantenimiento,
sin embargo, mantenibilidad y optimización pueden entrar en conflicto de manera que si nos centramos únicamente en aspectos de una de ellas, la otra salga perjudicada.
{\it Fowler}, en su libro {\it Refactoring} \cite{Refactoring},
da una posible solución a partir de la cual la optimización se integra en las últimas iteraciones de desarrollo,
después de haber refactorizado el diseño.
El problema es que, para mejorar la eficiencia, es posible que haya que volver a un estado de desarrollo anterior, en detrimento del diseño.
Con los tests de eficiencia, pretendemos integrar el modelo de desarrollo {\it XP} en
proyectos donde la optimización es necesaria desde las primeras iteraciones (sistemas de codificación multimedia, sistemas interactivos de tiempo real,...),
evitando así el problema de regresión anteriormente comentado.

Los tests de eficiencia comparan los tiempos de ejecución del código de diferentes momentos de su desarrollo,
notificando al usuario las variaciones de eficiencia importantes y permitiendo la visualización de dicha variación mediante una interfaz web.

El mayor problema a la hora de comparar dos o más tiempos de ejecución es la dependencia de los valores obtenidos respecto a factores externos como la ejecución de otros programas en paralelo, la arquitectura de la CPU y su velocidad, tamaño de la cache o el número de fallos de lectura y/o escritura.
Nuestro interés radica en aislar el cálculo del tiempo de todos estos factores de manera que el coste de tiempo obtenido para un código concreto sea el mismo siempre y cuando no haya ninguna modificación, de manera que los resultados sean comparables
sin dejar de ser realista.
Para poder independizar el resultado de algunas de las dependencias anteriormente citadas, una posible solución es el uso de {\it Valgrind}.
Valgrind es un framework para la ejecución instrumentada de programas que ofrece una API de plugins para instrumentar diversos aspectos del programa como el uso de memoria, el uso de recursos compartidos en un sistema concurrente o el uso de la cache entre otros.
El plugin usado en el proyecto es {\it Callgrind}, el cual instrumenta el tiempo de ejecución teniendo en cuenta varios aspectos como el uso de la cache, los jumps, el tipo de llamadas,...

Con el uso de {\it Callgrind} podremos comparar el tiempo de diferentes ejecuciones de manera fiable,
sin embargo, todavía queda pendiente evitar la regresión.
La regresión se produce cuando, en un proceso de mejora progresiva, se vuelve a un estado anterior en que se pierde dicha mejora.
La detección de la regresión de un proceso se puede llevar a cabo mediante el mantenimiento de un historial.
El aviso al usuario se realizaría con la monitorización de los cambios detectados.

Como la importancia de una subida o bajada de eficiencia depende directamente de lo crítico que sea el código evaluado, este proyecto ofrece una serie de alarmas configurables por el usuario, el cual será alertado en el caso que se cumplan las condiciones indicadas por éste.
Para asegurar el mantenimiento del historial, es interesante que, después de cada cambio en el código, se realice una nueva evaluación de eficiencia.
Por ello el proyecto presentado permite ser integrado en un sistema de ejecución automática de manera que con cada commit realizado del código en un sistema de control de versión (CVS, Subversion,...), se llevará a cabo una evaluación de eficiencia de forma automática.

En el último párrafo se ha planteado una solución para la regresión, sin embargo, aún no se ha especificado qué código queremos controlar.
Si se realiza un cálculo de eficiencia del sistema en general, será complicado averiguar qué modificaciones de código han implicado una variación de eficiencia. 
Con el software que presentado,
el código se aislará en casos de test de forma parecida a como se hace en {\it Test Driven Development}.
Así pues organizaremos la evaluación de eficiencia mediante suites de tests, donde cada test evaluará un código concreto.
Los nombres de los tests seguirán una misma estructura de manera que puedan ser identificados 

Finalmente, para que el usuario pueda acceder a los resultados que se han ido generando,
se desarrollará una interfaz web para que los datos se puedan visualizar mediante listados de los tests ordenados por su variación de eficiencia y mediante gráficas a partir de los cuales el usuario vea cómo ha variado la eficiencia del test a partir de las modificaciones realizadas en el código.




