martes, 19 de agosto de 2014

Debugging - Optimizacion (II)

En el anterior artículo vimos como modificando las opciones de compilador podíamos lograr una notable mejora en el tiempo de ejecución de un programa. (Sobre todo pensemos en programas batch que en cada ejecución deben de procesas cientos de miles de registros: Grandes entidades financieras, Agencias estatales de tributación, seguridad social, etc, etc.).

Vamos a analizar el código ensamblador que nos genera cada una de las compilaciones. Veamos primero el del programa compilado sin opciones de optimizaciòn:



Vemos la carga en la pila de los tres parámetros de la función y a continuación la llamada a la función sumaternaria().

Y en la imagen:



Vemos claramente las operaciones de suma en las líneas 17 a 21 y en la la línea 26 la instrucción return que nos lleva al programa principal.

Hasta aquí no hay nada no esperado.

Ahora vamos al listado ensamblador del programa compilado con la opción de máxima optimización. Y veamos si ha habido una mejora en el código de la función sumaternaria()




Vemos que hay una diferencia la suma ocupa menos instrucciones y opera directamente sobre la pila en vez de andar cargando  los valores en los registros y operando aritméticamente entre los registros. ¿Justificará este ahorro de instrucciones la diferencia de tiempos?.

Vayamos a la línea principal del programa para ver si  también hay diferencias:



La principal diferencia es que no hay llamada a la función sumaternaria(), ¿como es posible?. Antes de ver lo que está ocurriendo la primera conclusión es que si no hay llamada a la función las mejoras que hemos comentado antes tampoco tienen efecto. ¿De donde sale ese ahorro de tiempos?.

Fijémonos en las lineas 53, 54 y 55.. Este código no es más que la carga de parámetros para función printf() y la primera de ellas lo que hace es cargar en la pila el valor 6. Justamente 6 es la suma de los tres números que pasamos como parámetros a la función sumaternaria(). Para estar seguro de ello, volvemos a compilar el programa con la opción -O3 pero esta vez la llamada a la función será con otros valores:

sumaternaria(11, 12, 13);

Y buscamos en el nuevo listado



Vemos como esta vez se carga el valor 36 que corresponde a la suma de 11, 12, y 13. Con lo que confirmamos que el compilador carga directamente el valor de la suma.

Conclusión.


El compilador detecta que se está llamando a una función con valores fijos y coloca directamente el resultado en la pila para la siguiente función.

Por muchas razones: ciclos de cpu, paginación, etc esta codificación si justifica el ahorro de tiempo que hemos visto en las pruebas y, en determinadas condiciones, podría haber sido incluso más.

En el próximo artículo entraremos un poco a analizar los grupos de opciones y sacaremos alguna conclusiones más que deberemos tener en cuenta a la hora de optimizar nuestros programas.




No hay comentarios:

Publicar un comentario