Search code examples
pythonmemory-managementpsutildel

Why doesn't psutil accurately represent available memory after deleting a class instance in Python?


I'm currently struggling to find out how much memory I actually have left on my device after I have deleted an instance of a class. I have tried to use the library psutil but it doesn't correctly show the memory I actually have available. In particular:

import psutil

    x = torch.randint(0,255,size=(300,3,200,200),dtype=torch.float32)
    conv = Modules.Conv2D(3,3,2,10,save_flag=False)
 print("Used memory:", psutil.virtual_memory().percent,"% Free memory:", round(psutil.virtual_memory().available * 100 /
          psutil.virtual_memory().total),"%")
#Used memory: 74.0% Free memory: 26.0 %

conv is an object of my custom class and It has different attributes that take up a lot of memory(as you can see from psutil). Now If I try the following:

import gc

del conv
gc.collect()
 print("Used memory:", psutil.virtual_memory().percent,"% Free memory:", round(psutil.virtual_memory().available * 100 /
          psutil.virtual_memory().total),"%")
#Used memory: 74.0% Free memory: 26.0 %

Even if I delete the instance and I explicitly call python's garbage collector, the memory doesn't seem to be freed up. Although if I check with Windows' resource manager the memory is actually emptied:

#Before executing the program --> In use: 6025 MB
exec_program()
#Program is executing and conv instance is allocated --> In use: 6899 Mb
# gc.collect is called --> In use: 6058 Mb
end_of_program()

So the problem is that psutil doesn't represent correctly this situation. My guess is that although the memory is freed up by gc.collect the virtual memory address is still marked as used even if it is actually empty, hence the misrepresentation. Is there any other way/library that can do correctly what I'm trying to achieve? Thanks in advance!


Solution

  • Oops, memory allocation and deallocation is often a grey zone, where few things are guaranteed, either at Python level, or even at OS one. Specifically you cannot know whether deleting something at Python level will put the freed memory into a (process) local free list or will return it to the OS.

    That local free list exists because when a program does a lot of memory allocation/deallocation, it is far more efficient to keep the memory local than to return it back to the OS to later ask for it again. Said differently, psutil does its job and tells you how much memory is given to a specific process. But it does not know (hence cannot tell you) how the memory is used by the process...