[pyar] Caches - Uso y desperdicio de RAM vs. CPU

Claudio Freire klaussfreire en gmail.com
Jue Mar 26 21:50:27 ART 2015


2015-03-23 16:40 GMT-03:00 Marcos Dione <mdione en grulic.org.ar>:
> On Mon, Mar 23, 2015 at 04:37:27PM +0100, Alejandro Santos wrote:
>> 2015-03-23 16:31 GMT+01:00 Andres Riancho <andres.riancho en gmail.com>:
>> >     Y que te parece el tema en relacion a calcular el tamaño del cache
>> > de manera dinamica segun los recursos disponibles?
>>
>> Ni idea cómo calcularlo. AFAIK usás toda la RAM que quieras/puedas
>> hasta que sea acabe.
>>
>> Por ejemplo: lo que hacen los sistemas operativos modernos con los
>> archivos de disco (Windows Vista en adelante[0], Linux desde siempre)
>> es poner todo en RAM hasta que se acabe la RAM.
>
>     si, pero es distinto, porque el kernel maneja el tamaño de la la
> caché de disco en el sistema de manejo de memoria al reclamar páginas
> usadas para caché y dársela a la aplicación. en una aplicación ya estás
> fuera del loop que se entera de los cambios de este estilo. tomar toda la
> ram y dejar que el kernel la tire a swap cuando lo necesite es jugar con
> fuego, porque tu aplicación considera que todas las páginas que pidió
> están en memoria.

Lo he hecho y funciona, pero es verdad que es jugar con fuego.

Hay que conocer muy bien el patrón de acceso a memoria, y seguramente
(en el 99.99% de los casos) va a haber una solución mejor.

Volviendo al tema del OP, el tamaño del LRU lo tenés que decidir en
base al hit rate que quieras.

Decidí qué te parece aceptable. 90%? 99%? Y analizá tus patrones de
acceso (en este caso llamadas), y elegí el percentil adecuado. Por
ejemplo, si 99% de los accesos se concentran en 100 entradas, poniendo
un LRU de 100 entradas vas a tener un hit rate de aproximadamente 99%.
Y como es aproximado, yo siempre le doy un margen.

Hay que sopesar también el efecto de fragmentación que generan los
caches. Cuando cacheás agresivamente con un LRU, en python eso suele
fragmentar mucho la memoria (pues estás reteniendo objetos que
generaste en arenas - pools de objetos que usa el administrador de
memoria de python - que estaban llenas de temporales. Cuando terminás
el cálculo, se liberan los temporales pero el resultado queda. En el
sitio de pyar en la sección de charlas hay un par de charlas sobre
esto (ehem... mías), fijate que hay mucho detalle ahí.

La moraleja es que al caché lo limitás, no lo sizeás. El tamaño del
cache tiene que ser el mínimo que te da el hit rate que buscás. Todas
las entradas tienen que tener un TTL (tiempo de expiración), y tenés
que quitarlas cuando expiran, para no fragmentar de más.

Ni hablar si tu aplicación no va a ser lo único que corra en la
máquina. Con más razón tenés que ser conservador en el cacheo.

Lamentablemente, no es tan sencillo limitar un LRU a una cantidad de
RAM (o la cantidad de RAM libre), porque cuando cambie la cantidad de
RAM libre, no te enterás.

Si querés una implementación pure-python de muchas cosas de cacheo,
tenés este proyecto mío subdocumentado:

https://bitbucket.org/claudiofreire/chorde

Tiene muchísimas dependencias pesadísimas, pero todas opcionales ;-)


More information about the pyar mailing list