Memoization does not release memory after cache_clear
eldernewborn opened this issue · 1 comments
eldernewborn commented
Looking at the profiler output, it seems like cached decorator is not releasing memory:
32 2578.6 MiB 0.0 MiB 1 c = MemoizeClass()
33 2829.4 MiB 0.0 MiB 1001 for i in range(1000):
34 2829.4 MiB 250.8 MiB 1000 c.get_something(random.randint(0, 4000000000000))
35 2829.4 MiB 0.0 MiB 1 print(c.get_something.cache_info())
36 2829.5 MiB 0.1 MiB 1 print(len(list(c.get_something.cache_items())))
37 2829.5 MiB 0.0 MiB 1 print("############## flushing the cache ################")
38 2829.5 MiB 0.0 MiB 1 c.get_something.cache_clear()
39 2829.5 MiB 0.0 MiB 1 print(len(list(c.get_something.cache_items())))
40 2829.5 MiB 0.0 MiB 1 print(c.get_something.cache_info())
41 2829.5 MiB 0.0 MiB 1 print(f"found some Garbage:{len(gc.garbage)} items")
42 2829.5 MiB 0.0 MiB 1 print(f"collected: {gc.collect()}")
environment :
python 3.9.5
memoization: 0.4.0
code to reproduce the results. run with pytest -s
for best results.
from memory_profiler import profile
import gc
from memoization import cached
import random
import hashlib
class MemoizeClass:
def __int__(self):
self.unique = random.randint(0, 4000000000000)
@cached(max_size=1362)
def get_something(self, param):
return [param] * (2*10**5)
@profile
def test_memoization_cache():
print("\n")
c = MemoizeClass()
for i in range(1000):
c.get_something(random.randint(0, 4000000000000))
print(c.get_something.cache_info())
c = MemoizeClass()
for i in range(1000):
c.get_something(random.randint(0, 4000000000000))
print(c.get_something.cache_info())
del c
print(f"found some Garbage:{len(gc.garbage)} items")
print(f"collected: {gc.collect()}")
c = MemoizeClass()
for i in range(1000):
c.get_something(random.randint(0, 4000000000000))
print(c.get_something.cache_info())
print(len(list(c.get_something.cache_items())))
print("############## flushing the cache ################")
c.get_something.cache_clear()
print(len(list(c.get_something.cache_items())))
print(c.get_something.cache_info())
print(f"found some Garbage:{len(gc.garbage)} items")
print(f"collected: {gc.collect()}")
c = MemoizeClass()
for i in range(1000):
c.get_something(random.randint(0, 4000000000000))
print(c.get_something.cache_info())
eldernewborn commented
Comparing the behavior with functools :
32 2702.9 MiB 0.0 MiB 1 c = MemoizeClass()
33 2832.9 MiB -50638.2 MiB 1001 for i in range(1000):
34 2832.9 MiB -50508.2 MiB 1000 c.get_something(random.randint(0, 4000000000000))
35 2802.4 MiB -30.5 MiB 1 print(c.get_something.cache_info())
36 1661.3 MiB -1141.1 MiB 1 c.get_something.cache_clear()
37 1661.3 MiB 0.0 MiB 1 print("############## flushing the cache ################")
38 1661.3 MiB 0.0 MiB 1 print(c.get_something.cache_info())
39 1661.3 MiB 0.0 MiB 1 print(f"found some Garbage:{len(gc.garbage)} items")
40 1661.3 MiB 0.0 MiB 1 print(f"collected: {gc.collect()}")
Same environment
Code:
from memory_profiler import memory_usage,profile
import gc
from functools import lru_cache
import random
import hashlib
class MemoizeClass:
def __int__(self):
self.unique = random.randint(0, 4000000000000)
@lru_cache(maxsize=1362)
def get_something(self, param):
return [param] * (2*10**5)
@profile
def test_memoization_cache():
print("\n")
c = MemoizeClass()
for i in range(1000):
c.get_something(random.randint(0, 4000000000000))
print(c.get_something.cache_info())
c = MemoizeClass()
for i in range(1000):
c.get_something(random.randint(0, 4000000000000))
print(c.get_something.cache_info())
del c
print(f"found some Garbage:{len(gc.garbage)} items")
print(f"collected: {gc.collect()}")
c = MemoizeClass()
for i in range(1000):
c.get_something(random.randint(0, 4000000000000))
print(c.get_something.cache_info())
c.get_something.cache_clear()
print("############## flushing the cache ################")
print(c.get_something.cache_info())
print(f"found some Garbage:{len(gc.garbage)} items")
print(f"collected: {gc.collect()}")
c = MemoizeClass()
for i in range(1000):
c.get_something(random.randint(0, 4000000000000))
print(c.get_something.cache_info())