<body>

Sitios web relacionados: PingBlog | Fotos

miércoles, noviembre 23, 2005

Echando código: Cuando optimizamos y la defecamos...



Uno de los primeros programas que hice para la compañia en la que trabajo actualmente es un script en Perl que valida los contenidos de un archivo de texto. El archivo gobierna como se comportan instancias de al menos 500+ programas en Java, los cuales generan cientos de miles de calculos por segundo. El script nació para evitar que errores de configuración volvieran sopa al sistema, el cual por decirlo de alguna manera es bastante sensible.

Aprendiendo de experiencias pasadas, evité optimizar al principio, concentrandome en que el programa corriera bien; Poco a poco (y al ver que el sistema de verdad atabaja metidas de pata) los compañeros de el grupo decidieron que yo le agregara más pruebas, mientras que al mismo tiempo el script crecia y crecia hasta que de ejecutarse en 10 segundos pasó a 4 minutos.

¡Hora de optimizar! dije yo. Como el programa verifica un archivo de texto y este no es muy grande, decidí cargarlo todo en memoria. Para acelerar las pruebas, entonces decidí paralelizarlo utilizando "Perl Threads" y que cada una de ellas ejecutara sus pruebas en un pedazo de el archivo. Solamente algunas de ellas requerian procesar el archivo completo (como buscando duplicados) pero la mayoría eran independientes.

Ni corto ni perezoso lo parelicé; ¡De 4 minutos bajo a 30 segundos!. Emocionado, me disponía a publicarlo y se me ocurrió hacer una prueba más formal, con algunos casos obscuros. Para mi sopresa, el código sufria de condiciones de carrera, las pruebas no eran confiables y el código ahora era más complejo.

Que ladilla; Y justo cuando estaba a punto de ponerme a depurar el script algo me pegó en la cabeza:

¿Tu ya revizaste en donde pasa la mayor parte de el tiempo el programa?

No, no se me habia ocurrido hacerle un "profiling" a mi script. Recordando como hacerlo en Perl, encontré que el script pasaba %30 de el tiempo en dos rutinas, una de ellas la cual utilizaba la red para bajarse datos y la otra que buscaba el mismo valor una y otra vez.

El problema lo resolví utilizando un arreglo asociativo (Hash) para guardar valores de ambas pruebas (en hash distintos claro) y el tiempo bajó de 4 minutos a 6 segundos. Y lo mejor, el código es aún simple, sin threads.

Por supuesto no descarto usar threads en el futuro, pero por ahora 6 segundos es un tiempo bastante razonable. La moral de la historía es obvia, no empieces a optimizar sin saber que es lo que se puede mejorar (si suena obvio, pero más de una ves esto pasa cuando nos sentamos a programar sin planear un poquito).

Buscar en Technorati:

3 Comentarios:

Blogger jcamargo dijo que...

Felicitaciones por la optimización, escribes como si fuese una crónica y se pone interesante jeje

saludos desde bogotá

jorge c

1:46 PM (enlace permanente)  
Anonymous Tony::A&I dijo que...

Me fascino esto, soy tambien miembro de softwareven y me encanta lo q publicas.
Aprecio cada lectura
Salu2

7:16 PM (enlace permanente)  
Blogger fastonion dijo que...

Seria depinga, q pudieras colocar el codigo en perl con la estructura basica de como hacer el debug a tu aplicacion. Esta interesante tambien el como determinaste cual de los puntos del codigo presentaba mayor tiempo de procesamiento.

Del resto esta interesante el analisis. En cuanto a los threads tambien suena interesnte pero parece q esta en pañales aun por lo q he logrado leer.

1:17 PM (enlace permanente)  

Publicar un comentario en la entrada

Enlaces a este articulo:

Crear un vínculo

<< Regresar