Implementando el decorador de caché LRU en Python

LRU es el algoritmo de reemplazo de caché que elimina los datos usados ​​menos recientemente y almacena los datos nuevos. Supongamos que tenemos un espacio de caché de 10 marcos de memoria. Y cada cuadro se llena con un archivo. Ahora, si queremos almacenar el nuevo archivo, debemos eliminar el archivo más antiguo de la memoria caché y agregar el nuevo archivo. Así es como funciona LRU.
La memoria caché LRU consta de estructuras de datos de cola y diccionario. 
 

  • Cola: para almacenar desde los archivos usados ​​más recientemente hasta los menos usados 
     
  • Tabla hash: para almacenar el archivo y su posición en el caché 
     

Consulte los siguientes artículos para obtener más información sobre el tema: 
 

 

¿Qué es decorador?

Un decorador es una función que toma una función como su único parámetro y devuelve una función. Esto es útil para «envolver» la funcionalidad con el mismo código una y otra vez. 
Nota: Para obtener más información, consulte Decoradores en Python .
Ahora, después de obtener la idea básica sobre LRU y los decoradores en Python, echemos un vistazo a la implementación del decorador de caché LRU en Python.
 

Python3

from collections import deque
 
 
# LRU cache implementation
class LRUCache:
     
    def __init__(self, size=5):
        self.size = size
        self.container = deque()
        self.map = dict()
      
      
    def reallocate(self):
        # to reallocate the hashmap for
        # every access of file access file
        # will reallocate the data in hashmap
        # according to the numbers position
        # in the container for every access,
        # hit and miss(evict)
        if len(self.container) > 1:
             
            for key, val in enumerate(self.container):
                self.map[val] = key
      
      
    def access(self, val):
         
        # print("access "+str(val))
        self.container.remove(val)
        self.container.appendleft(val)
        self.reallocate()
      
    def evict(self, val):
         
        # print("cache miss "+str(val))
        if val in self.map:
            #del self.map[val]
            self.container.remove(val)
         
        else:
            x = self.container.pop()
            del self.map[x]
         
        self.normal_insert(val)
          
    def normal_insert(self, val):
        self.container.appendleft(val)
        self.reallocate()
          
    def insert(self, val):
         
        if val in self.map.keys():
             
            # if value in present in
            # the hashmap then it is a hit.
            # access function will access the
            # number already present and replace
            # it to leftmost position
            self.access(val)
             
        else:
            # if value is not present in
            # the hashtable
            if (len(self.map.keys()) == self.size):
                # if the size of the queue
                # is equal to capacity and
                # we try to insert the number,
                # then it is a miss then,
                # evict function will delete the
                # right most elements and insert
                # the latest element in the
                # leftmost position
                self.evict(val)
                 
            else:
                # normal_insert function will normally
                # insert the data into the cache..
                self.normal_insert(val)
      
    def print(self):
        lru_elements = [x for x in self.container]
        print(lru_elements)
  
  
 
# definition of lru decorator
def LRUDecorator(size):
     
    lru = LRUCache(size)
     
    def decorator(function):
         
        def functionality(num):
            lru.insert(num)
            lru.print()
             
            # to check the num pageframe(position)
            # uncomment the below statement
            # print(lur.map)
            print(num, function(num))
        return functionality
     
    return decorator
  
     
# Using LRU Decorator
@LRUDecorator(size=4)
def ex_func_01(n):
    print(f'Computing...{n}')
    time.sleep(1)
    return n
          
print(f'\nFunction: ex_func_01')
print(ex_func_01(1))
print(ex_func_01(2))
print(ex_func_01(3))
print(ex_func_01(4))
print(ex_func_01(1))
print(ex_func_01(2))
print(ex_func_01(5))
print(ex_func_01(1))
print(ex_func_01(2))
print(ex_func_01(3))
print(ex_func_01(4))
print(ex_func_01(5))

Producción:
 

Function: ex_func_01
[1]
Computing...1
1 1
None
[2, 1]
Computing...2
2 2
None
[3, 2, 1]
Computing...3
3 3
None
[4, 3, 2, 1]
Computing...4
4 4
None
[1, 4, 3, 2]
Computing...1
1 1
None
[2, 1, 4, 3]
Computing...2
2 2
None
[5, 2, 1, 4]
Computing...5
5 5
None
[1, 5, 2, 4]
Computing...1
1 1
None
[2, 1, 5, 4]
Computing...2
2 2
None
[3, 2, 1, 5]
Computing...3
3 3
None
[4, 3, 2, 1]
Computing...4
4 4
None
[5, 4, 3, 2]
Computing...5
5 5
None

Publicación traducida automáticamente

Artículo escrito por krishna krish y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *