After noticing that memory was not being freed in a GUI app, I made a simple test:
import gc
class Item:
def __init__(self, parent=None):
self.items = []
self.parent = parent # If this is commented, the gc works as expected
def create():
__root = Item()
for i in range(2000000):
new = Item(__root)
__root.items.append(new)
return __root
def dummy():
root = create()
input("In dummy function")
dummy()
input("After dummy function")
gc.collect()
input("After garbage collect")
This simple tree structure has a list of items that point to the parent. When the execution reaches the second input
prompt, I was expecting to see the memory freed, but it's not.
If I manually call gc.collect()
the memory does get freed. Also, if I remove the reference to the parent, of if I make it a weakref
then the garbage collector frees the memory automatically without manually calling gc.collect()
.
Why does this happen? Isn't this how the garbage collector is supposed to work?
UPDATE:
After some more experiments, I noticed the garbage collector does seem to work...but in a dumb way. It doesn't free the memory, instead it reserves it. So when new objects are created, they are using this reserved space without increasing the total memory used.
This is a big issue for me because I have a GUI app with multiple sub windows, each potentially loading up to 1GB of data. When I open a few sub windows simultaneously, almost the entire RAM is used. The huge problem is that after I close the sub windows, the RAM is not freed...it's in this reserved state.
Every now and then, upon opening a new sub window, a big portion of this RAM is freed, but overall there is still a huge amount of memory that is not released to the OS.
I don't understand the usefulness of such a garbage collector.
Copyright License:
Author:「bombos」,Reproduced under the CC 4.0 BY-SA copyright license with link to original source & disclaimer.
Link to:https://stackoverflow.com/questions/65064454/python-simple-circular-reference-not-removed-by-garbage-collector