Python no es C...

Imagen de soulnet

… y las cosas no se hacen igual.

Este post tiene su origen, como tantos otros, en cosas triviales: Leía el libro “Rapid GUI programming with Python and QT” (que interesante soy :P) cuando me topé con una instrucción que no conocía: unichr(i). Este built-in devuelve el carácter unicode que representa el entero i.

Por simple curiosidad hice un pequeño script que guardase en un fichero los caracteres unicode del 1 al 65536. Como aún arrastro muchos vicios de C, resultó en lo siguiente:

salida=u""
f = open("/tmp/unicode-slow.txt", "w")

for t in xrange(1, 65535):
    salida = salida + u",%s" % unichr(t)

f.write(salida.encode("utf-8"))
f.close()

Típico, iterar por todos los valores de los caracteres unicode a representar e ir concatenándolos a una cadena.

Este script en mi portátil (G4@1.2Ghz) tarda la friolera de 1 minuto y 33 segundos en ejecutarse… Un SSH a mi equipo de sobremesa (Q6600@2.4Ghz) muestra que ahí tarda 5.31 segundos.

Ante estas cifras no pude menos que ponerme a pensar en la forma de rebajar tiempos, y me di cuenta de que la culpa de esa cantidad tan brutal de segundos la tiene mi empeño en programar “The C way” en lugar de “The Python way”.

Así que la nueva versión resulta:

salida=u""
f = open("/tmp/unicode-fast-list.txt", "w")

salida = [unichr(t) for t in xrange(1, 65535)]
f.write(",".join(salida).encode("utf-8") )

f.close()

“Uhmmmm… si uso un un generador en lugar de una lista podría rascar algo de tiempo”. Así que la versión definitiva queda como:

salida=u""
f = open("/tmp/unicode-fast-generator.txt", "w")

salida = (unichr(t) for t in xrange(1, 65535))
f.write(",".join(salida).encode("utf-8") )

f.close()

(En efecto, solo cambian los corchetes por paréntesis)

La diferencia de tiempo de ejecución entre los tres scripts es tan bruta, que prefiero mostrarla gráficamente:

Tiempos de ejecución

¡En mi portátil, las nuevas versiones son 344 y 404 veces más rápida que la antigua! (93s/0.27s y 93s/0.23s, respectivamente). En el sobremesa esta diferencia se queda en “solo” 129 y 151 veces más veloz.

Para apreciar la diferencia entre los métodos más rápidos:

Tiempos de ejecución - detalle

A pesar de que la diferencia entre la versión de lista y el generador no parece muy grande, 0.04 segundos es una eternidad para una CPU :)

Así que la moraleja de la historia es… se consecuente con el lenguaje de programación que usas, y serás más feliz :P

Gráficas creadas con Create a graph

Comentarios


Con algo así hemos conseguido rebajar los tiempos de carga en WordPress 2.6 :)

Nos estamos pasando todos a the python way.


Friki, muy Friki Soulnet. Pero en verdad llevas razón apañero.

Habrá que echarle un vistazo “the python way

Enviar un comentario nuevo

El contenido de este campo se mantiene como privado y no se muestra públicamente.