Reference counting & GC
Overview
Python manages memory automatically using reference counting: every object keeps a count of how many labels point to it. When the count drops to zero, the object is immediately destroyed. A 'cyclic reference' occurs when objects point to each other (e.g., node A points to B, and B points to A). Reference counting cannot clean these up because their counts never reach zero. To solve this, a background process called the 'garbage collector' periodically scans for unreachable cycles and destroys them. Think of reference counting as returning a library book as soon as you finish reading it, and the garbage collector as the librarian sweeping the building at night for abandoned books.
It prevents memory leaks in long-running applications without requiring developers to manually allocate and free memory.
Where used: FastAPI background tasks, Celery workers, Data processing scripts
Why learn this
- You can avoid creating memory leaks in long-running servers.
- You understand why the gc module exists and when to use it.
Code walkthrough
import sys
x = []
print(sys.getrefcount(x))
y = x
print(sys.getrefcount(x))
del y
print(sys.getrefcount(x))
Focus: del y
Common mistakes
- Unintentional cycles caching: Storing large objects in global dictionaries or caches that reference each other, preventing memory from being freed until the program ends.
- Assuming del deletes objects: The del statement only deletes the variable name (the label), not the object. The object is only destroyed if that was the last label pointing to it.
Glossary
- reference counting
- A method of memory management where Python keeps track of how many times an object is being used. Example: `sys.getrefcount(obj)`
- memory leaks
- When a program fails to release memory that it no longer needs, eventually causing the system to run out of memory. Example: `storing unused data in a cache`
Recall questions
- What is the primary mechanism Python uses to know when to delete an object?
- Why is a secondary garbage collection process needed in addition to reference counting?
Understanding checks
What is the output of this code?
True
When a and b are deleted, their reference counts drop to 1 (because they point to each other). `gc.collect()` finds this unreachable cycle, cleans it up, and returns the number of collected objects, which is greater than 0.
If you delete a variable using `del x`, does it immediately free the memory?
Not necessarily. It only decrements the reference count.
`del x` removes the label 'x' and decrements the object's reference count by 1. The object is only destroyed and its memory freed if that count reaches 0.
Practice tasks
Break a cycle
The provided code creates a cyclic reference between a parent and child node. Modify the code to manually break the cycle before the end of the script so that reference counting alone can clean them up.
Challenge
Analyze Reference Counts
Create a list a and append it to itself. Then delete the label a. This creates a cyclic reference. Use the gc module to force a collection and print the number of collected objects.
Continue learning
Previous: Variables as references
Previous: Mutable vs immutable types