sql >> Base de Datos >  >> NoSQL >> MongoDB

Python:construyendo un caché LRU

La caché LRU en Python3.3 tiene inserción, eliminación y búsqueda O(1).

El diseño utiliza una lista circular de entradas con doble enlace (ordenadas de la más antigua a la más nueva) y una tabla hash para ubicar enlaces individuales. Los hits de caché usan la tabla hash para encontrar el enlace relevante y moverlo al encabezado de la lista. La memoria caché no elimina el enlace más antiguo y crea un nuevo enlace al principio de la lista de enlaces.

Aquí hay una versión simplificada (pero rápida) en 33 líneas de Python muy básico (usando solo operaciones simples de diccionario y lista). Se ejecuta en Python2.0 y versiones posteriores (o PyPy o Jython o Python3.x):

class LRU_Cache:

    def __init__(self, original_function, maxsize=1024):
        # Link structure: [PREV, NEXT, KEY, VALUE]
        self.root = [None, None, None, None]
        self.root[0] = self.root[1] = self.root
        self.original_function = original_function
        self.maxsize = maxsize
        self.mapping = {}

    def __call__(self, *key):
        mapping = self.mapping
        root = self.root
        link = mapping.get(key)
        if link is not None:
            link_prev, link_next, link_key, value = link
            link_prev[1] = link_next
            link_next[0] = link_prev
            last = root[0]
            last[1] = root[0] = link
            link[0] = last
            link[1] = root
            return value
        value = self.original_function(*key)
        if len(mapping) >= self.maxsize:
            oldest = root[1]
            next_oldest = oldest[1]
            root[1] = next_oldest
            next_oldest[0] = root
            del mapping[oldest[2]]
        last = root[0]
        last[1] = root[0] = mapping[key] = [last, root, key, value]
        return value


if __name__ == '__main__':
    p = LRU_Cache(ord, maxsize=3)
    for c in 'abcdecaeaa':
        print(c, p(c))

A partir de Python 3.1, OrderedDict hace que sea aún más simple implementar un caché LRU:

from collections import OrderedDict

class LRU_Cache:

    def __init__(self, original_function, maxsize=1024):
        self.original_function = original_function
        self.maxsize = maxsize
        self.mapping = OrderedDict()

    def __call__(self, *key):
        mapping = self.mapping
        try:
            value = mapping[key]
            mapping.move_to_end(key)
        except KeyError:
            value = self.original_function(*key)
            if len(mapping) >= self.maxsize:
                mapping.popitem(False)
            mapping[key] = value
        return value