Can we have a LRU type of dictionary

Hi,

I am having some sort of memory leak in my code. I am doing something like

_BUILDERS : dict[Config,Builder] = dict()

def _get_builder(cfg : Config) -> Builder:
    if cfg in _BUILDERS:
        return _BUILDRS[cfg]

   builder = bulild_builder()
   _BUILDERS[cfg] = builder

   return builder

However when the _BUILDERS dictionary gets too large, it causes troubles. In reality I might only need the last 10 builders. One posibility is to use dequee. However this would make it harder to find the key and the code would get messy. Is there a reason why a limited size dictionary does not exist? Something like:

_BUILDERS : dict[Config,Builder] = dict(max_size=10)

Cheers.

There is a LRU cache doing what you are looking for.


@functools.lru_cache(maxsize=10)
def _get_builder(cfg : Config) -> Builder:
    return bulild_builder()
7 Likes

Hi Acampove,

I believe Xitop provided a good solution, however it does leave me with a question - is build_builder truly independent of cfg? If I understand you code correctly, _BUILDERS is supposed to be a cache, yet when you insert new elements to it, they are not composed of cfg or any sub-element of it (unless it is like a seed for a RNG), so how would you meaningfully map cfg to the result of build_builder?

OrderedDict might work here. It is deque-like in that new entries are ordered and there is a popitem(False) method for getting rid of old stuff when the dictionary gets too big. Unlike a deque, finding a key is still clean and fast.

1 Like

Hi @YuvalYuval

No, it’s not independent, it turns out that the idea came from a bad design. I actually can achieve this with a function wrapped with β€œ@cache”. In that case, the function itself can be used as a dictionary.