From: CaStarCo <cas...@gm...> - 2009-12-12 16:50:29
|
Perdon, di mal los comandos, que son (respectivamente para cada uno de los casos comentados): git pull origin reformed_styles_cache git pull origin without_styles_cache git pull origin master Voy a comentar brevemente el código que hice, pues ayer solo hice un anuncio demasiado escueto. Utilizando el módulo mmap de python se pueden hacer llamadas a la función de sistema mmap que sirve para mapear ficheros en memoria, en particular si se le pasa el descriptor de fichero -1 crea una área de memoria anónima no asociada a ningún fichero. Si ése área de memoria y el descriptor de fichero asociado se crean antes de hacer el fork , el descriptor de fichero es compartido por todos los ficheros, con lo que se puede usar esa área de memoria compartida para comunicar los procesos y establecer una cache comun... que es lo que hice. ¿Cuál es el problema? Pues que Python no da un soporte implícito a la compartición de objetos entre procesos por la misma razón que se implementó el GIL, para evitar los problemas de inseguridad inherentes al acceso concurrente a estructuras de datos en memoria... vamos, que Python no es thread-safe. Por eso mismo para poder mapear el diccionario que uso como cache en memoria tengo que usar el módulo pickle, que sirve para serializar objetos... tiene sus limitaciones, pero ya me sirve. El caso es que no he podido calcular las mejoras/empeoramientos de rendimiento debidos a ésta cache dado que no se me ocurre ningún metodo y no puedo someter tabularium a una carga intensiva de trabajo debido a que no hay usuarios. ¿A alguien se le ocurre un experimento decente que permita verificar si el rendimiento mejora o empeora? Bien, lo digo porque en principio sería de esperar que el rendimiento mejorara si no fuera por el hecho de que todo el proceso que sigo para tratar con la cache aumenta la intensidad de los cálculos (aunque nos libera de accesos a disco y comunicaciones con la base de datos, que podría ser remota). Es por eso que no tengo tan claro hasta qué punto eso supone una mejora... (aunque, ahora viene la sorpresa :D , agradable por cierto) A parte de los problemas que conlleva la creación de la cache tal y como he comentado hasta ahora, hay más, resulta que se debe calcular a priori un tamaño razonable para la cache... y eso depende mucho del funcionamiento interno de pickle (que podría variar con cada versión de Python), por lo que uno debe ser "generoso" y además esto hace que aparezcan "números mágicos" difíciles de justificar en medio del código (que provienen de la experimentación). No creo que sea una buena práctica de programación depender de esos "números mágicos". Y la alegría: he descubierto un método mejor xD. Y os preguntaréis... ¿y para que todo este rollo? Pues para que podáis apreciar por qué razón lo que sigue és obviamente mejor. ¿Alguien de por aquí sabe lo que és memcached? Bien, pues es un sistema que sirve para crear caches en memoria... pero obviamente mucho más optimizado de lo que yo haya podido hacer hasta el momento (en gran parte porque está creado en C y no en Python y porque los desarrolladores se han esmerado en ello y ese era su objetivo básico). Memcached funciona de la siguiente manera: se levanta un servidor que crea un área de memoria compartida del tamaño que se le indica durante su arranque, éste servidor está disponible a través de un puerto que también se especifica durante su arranque y sirve para almacenar objetos, no simples cadenas de la misma forma que yo lo hacía con mmap y pickle, sino los objetos en sí (se simplifica la gestión), y tratados con código optimizado escrito en C. Además se le puede asociar a cada objeto un tiempo de vida... lo que en parte serviría para eliminar código como el que yo usaba para eliminar los elementos más antiguos de la cache... pasa de ser código en Python a ser código altamente optimizado en C. Hay más ventajas, esa cache no solo sirve para el ejemplo de los estilos, puede ser una cache comun que se utilize para cualquier tipo de objeto, lo que simplifica en gran medida la gestión interna de tabularium de las caches de datos mantenidas en memoria. Entonces.. qué hay que hacer para utilizar memcached? En debian y ubunut: instalar memcached y python-memcache... el código lo podréis ver en breve en cuanto reemplaze la versión actual de tabularium con cache por la siguiente usando el servidor de memcached. Saludos! Referencias: [0] http://blog.isotoma.com/2009/09/memcache-in-2-minutes/ [1] http://blog.isotoma.com/2009/09/of-python-memcached-and-decorators-easy-peasy-function-caching/ P.D.: No estoy muy metido en GuPy, pero creo que es recomendable dar a conocer allí cosas como éstas: mmap, pickle, memcached, tornado ... El día 11 de diciembre de 2009 23:26, CaStarCo <cas...@gm...> escribió: > Bien, he creado dos ramas diferentes para tabularium, una con cache > para estilos y otra sin. La sin... sin novedades, vamos, sin cache y > punto. > > La con: he conseguido crear una cache compartida en memoria usando > mmap y el modulo pickle, podéis ver el código en los repos . Pero > teneis que hacer: > > para con cache: > git pull reformed_styles_cache > > sin cache: > git pull without_styles_cache > > sin eliminar la cache.. y con los bugs de antes: > git pull master > > Saludos! > > (Estaría bien testear a ver cual rinde más de las dos primeras.. (la > tercera queda descartada)) > > -- > - Per la llibertat del coneixement - > - Per la llibertat de la ment... - > -- - Per la llibertat del coneixement - - Per la llibertat de la ment... - |