2011-09-22 21 views
8

Mientras leía la documentación en el módulo Python re, decidí echar un vistazo al código fuente re.py.Limitación de caché del módulo Python re

cuando la abrí, me encontré con esto:

_cache = {} 
_MAXCACHE = 100 

def _compile(*key): 
    cachekey = (type(key[0]),) + key 
    p = _cache.get(cachekey) 
    if p is not None: 
     return p 

    #...Here I skip some part of irrelevant to the question code... 

    if len(_cache) >= _MAXCACHE: 
     _cache.clear() 
    _cache[cachekey] = p 
    return p 

¿Por qué es la memoria caché se aclaró usando _cache.clear() cuando alcanza _MAXCACHE de las entradas?

¿Es un enfoque común limpiar completamente la caché y comenzar desde cero?

¿Por qué no se utilizó hace más tiempo que se elimina el valor en efectivo?

+3

Pregunta interesante. Supongo que podría haber sido la pereza por parte del desarrollador que escribió este código, o tal vez el pensamiento "El simple es mejor que el complejo". :-) – NPE

+0

Pensé que podría haber alguna investigación científica que justificara ese enfoque de borrar el caché al alcanzar un valor constante de tamaño. – ovgolovin

+0

Puede ser interesante ver el origen del nuevo módulo de expresión regular en desarrollo, que se rastrea aquí: http://bugs.python.org/issue2636. La descripción incluye el término "Almacenamiento en caché inteligente", por lo que puede haber algunas mejoras realizadas en esa área. –

Respuesta

3

Si tuviera que adivinar, diría que se hizo de esta manera para evitar tener que hacer un seguimiento de cuándo/cuánto tiempo se almacenaron los valores individuales en la caché, lo que crearía memoria y procesamiento. Debido a que el objeto de almacenamiento en caché que se utiliza es un diccionario, que por naturaleza no está ordenado, no hay una buena forma de saber qué elementos de pedido se agregaron sin algún otro objeto de almacenamiento en caché. Esto podría abordarse utilizando un OrderedDict en lugar de un diccionario estándar, suponiendo que está trabajando con Python> = 2.7, pero, de lo contrario, tendría que rediseñar significativamente la forma en que se implementó el almacenamiento en caché para eliminar la necesidad de un clear().

+0

¿Es difícil implementar 'caché' usando' OrderedDict'? En mi opinión, usar el orden de los elementos hace que sea posible ordenarlos por orden de uso. Y la reutilización de un objeto compilado solo requeriría mover el valor almacenado en caché al principio de 'OrderedDict' mostrándolo y colocándolo nuevamente en el diccionario. – ovgolovin

+0

@ovgolovin - Se puede hacer pop/re-agregar el valor para moverlo al final de la lista, es posible. No lo consideraría difícil, no. –

+0

Pensé que podría haber alguna investigación científica que justifique tal enfoque de borrar el caché al alcanzar un valor de tamaño constante. – ovgolovin

1

El objetivo del almacenamiento en caché es disminuir el tiempo de llamada promedio de la función. La sobrecarga asociada con mantener más información en _cache y podarla en lugar de borrarla incrementaría ese tiempo de llamada promedio. La llamada _cache.clear() se completará rápidamente, y aunque pierda su caché, es preferible mantener un estado de caché y tener la sobrecarga de eliminar elementos individuales de la caché cuando se alcanza el límite.

Hay algunas cosas en que pensar cuando se calcula la eficiencia de caché:

  1. Tiempo medio de llamada en aciertos de caché (muy corto)
  2. Tiempo medio de llamada en fallos de caché (más)
  3. de frecuencia de aciertos de caché (muy común) para el tiempo cuando se borra la memoria caché o podado (muy común) para
  4. llamada

La pregunta es si aumentar el n. ° 3 tiene sentido si significa aumentar también los n. ° 2 y n. ° 4. Supongo que no, o la diferencia es lo suficientemente insignificante para mantener el código simple es preferible.

+0

Pero la sobrecarga asociada con el mantenimiento de más información en '_cache' será predecible. Pero eliminar '_cache' en momentos esporádicos hará que la evaluación de la eficacia de la memoria caché sea muy molesta, ya que será muy confiable en los momentos en que se elimine' caché '. – ovgolovin

5

Aquí hay una cita de uno de los desarrolladores de un nuevo módulo regex programado para 3.3 con respecto al almacenamiento en caché, esto es parte de una lista de características que separa el nuevo módulo del módulo actual re.

7) Modifique la memoria caché de expresiones compiladas para manejar mejor la condición de agitación de . Actualmente, cuando se compilan las expresiones regulares, el resultado se guarda en caché para que, si se vuelve a compilar la misma expresión, se recupere de la memoria caché y no se tenga que realizar ningún trabajo adicional. Esta caché admite hasta 100 entradas. Una vez que se alcanza la entrada número 100, la memoria caché se borra y debe producirse una nueva compilación.El peligro, sea raro , es que uno puede compilar la centésima expresión solo para encontrar que uno lo recompila y tiene que hacer el mismo trabajo una vez más cuando se han hecho hace 3 expresiones. Modificando ligeramente esta lógica, es posible establecer un contador arbitrario que da una marca de tiempo a cada entrada compilada y en lugar de borrar toda la caché cuando alcanza , solo elimina la mitad más antigua de la caché, manteniendo la mitad es más reciente. Esto debería limitar la posibilidad de azotar a los casos en los que se recompila continuamente un gran número de expresiones regulares . Además de esto, actualizaré el límite a 256 entradas, lo que significa que se guardan las 128 más recientes.

http://bugs.python.org/issue2636

Esto parece indicar que es más probable que la pereza del desarrollador o "énfasis en la facilidad de lectura" que explica el comportamiento de caché actual.

+0

He abierto el código fuente del módulo 'regex' (lo he usado durante aproximadamente una quincena). El bloque de código que se encarga de borrar el caché es el siguiente 'if len (_cache)> = _MAXCACHE: shrink_cache (_cache, _named_args, _MAXCACHE)'. Pero no he encontrado ninguna función 'shrink_cache' en el módulo. No hay tal función – ovgolovin

+0

Aún así, el autor se mantiene con la eliminación de grandes cantidades de caché, no solo elemento cuando es necesario. El nuevo enfoque elimina la mitad menos reciente de la memoria caché. – ovgolovin

Cuestiones relacionadas