Skip to content

The Generational Garbage Collector

While Reference Counting is Python’s primary memory manager, it has a blind spot: Circular References. If two objects point to each other but are no longer used by the program, reference counting will never delete them.

To solve this, Python includes a secondary system: the Generational Garbage Collector (GC).


Imagine a parent and a child object that both hold references to each other.

cycle.py
class Node:
def __init__(self, name):
self.name = name
self.link = None
# Create cycle
a = Node("Parent")
b = Node("Child")
a.link = b
b.link = a
# Delete the external labels
del a
del b

Even though you can no longer access these objects, their reference count remains at 1. They are “Islands of Isolation” that would leak memory forever if not for the GC.


The Python GC is based on a simple observation in computer science: Most objects die young.

Python organizes all objects into three Generations:

  1. Generation 0: Newly created objects.
  2. Generation 1: Objects that survived one GC sweep of Gen 0.
  3. Generation 2: Objects that survived multiple GC sweeps.
  • Frequent: Python scans Gen 0 very often.
  • Less Frequent: If Gen 0 is scanned many times, Python scans Gen 1.
  • Rare: Only when Gen 1 has been scanned many times does Python perform a full sweep of Gen 2.

This strategy is efficient because it focuses the CPU’s effort on the objects most likely to be garbage (the new ones).


How does the GC know which objects are part of a cycle? It uses an algorithm that “walks” the graph of objects.

  1. Root Set: The GC starts with objects it knows are alive (globals, stack variables).
  2. Marking: It follows every reference from the root set and marks those objects as “Reachable.”
  3. Sweeping: Any object that was not reached during the walk is considered “Unreachable” and is deleted, even if its reference count is not zero.

You can inspect and tune the garbage collector using the built-in gc library.

gc_control.py
import gc
# 1. Check current thresholds (when GC triggers)
print(gc.get_threshold()) # Default: (700, 10, 10)
# 2. Force a full collection manually
collected = gc.collect()
print(f"Garbage collector: cleaned {collected} objects.")
# 3. Disable GC (Use with extreme caution!)
# gc.disable()

FeatureReference CountingGenerational GC
TriggerImmediate (on refcnt == 0).Periodic (based on thresholds).
ComplexitySimple and Fast.Complex and Expensive.
Handles Cycles?No.Yes.
PredictabilityDeterministic.Non-deterministic.