python GC(Garbage Collector)
This post was migrated from Tistory. You can find the original here.
Python Garbage Collector
Basically, objects get freed via reference counting, and on top of that, Generational Garbage Collection seems to kick in whenever a generation’s threshold is crossed.
Reference Counting
When an object’s reference count hits 0, it gets garbage collected.
Generational Garbage Collection
This is the GC mechanism that solves the problem reference counting can’t handle on its own: circular references, where the count never reaches 0.
It’s built around the concepts of generations and thresholds.
1
2
3
import gc
print(gc.get_threshold()) #(700, 10, 10)
The tuple represents generation 0, generation 1, and generation 2, in that order.
As long as the number of generation-0 objects stays under 700 (the threshold), garbage — including circular references — just sits allocated in memory.
Once the threshold is exceeded, the generational GC runs, and any objects that survive get promoted to the next generation.
The threshold for generation 1 is 700*10, and for generation 2 it’s 700*10*10.
Generational GC runs by fully pausing the application (stop-the-world).
Because of that, the thresholds are configurable, which gives you a tradeoff:
use more memory and you can space out GC cycles further apart,
or run GC cycles more frequently and use less memory.
+ Extra
1
2
3
4
5
6
7
8
9
10
11
class Test:
def __init__(self, i) -> None:
print(gc.get_count())
print(f"hi {i} id:{id(i)}")
def __del__(self):
print(f"bye {i} id:{id(i)}")
for i in range(3):
test = Test(i)
# del(test)
1
2
3
4
5
6
7
8
9
(237, 1, 1)
hi 0 id:140718906091280
(238, 1, 1)
hi 1 id:140718906091312
bye 1 id:140718906091312
(238, 1, 1)
hi 2 id:140718906091344
bye 2 id:140718906091344
bye 2 id:140718906091344
The first object created doesn’t get destroyed automatically…? And for the last one, the destructor ran twice. (Not sure why yet.)
1
2
3
4
5
6
7
8
9
(237, 1, 1)
hi 0 id:140718906091280
bye 0 id:140718906091280
(237, 1, 1)
hi 1 id:140718906091312
bye 1 id:140718906091312
(237, 1, 1)
hi 2 id:140718906091344
bye 2 id:140718906091344
If you explicitly call del at the end of each loop iteration, you get the expected result.
References
https://medium.com/dmsfordsm/garbage-collection-in-python-777916fd3189