Memory Model & GIL
Overview
Learn how Python manages object allocation, performs garbage collection, and structures thread tasks with the GIL.
Learning Objectives
- Learn reference counting and generational garbage collection.
- Understand the Global Interpreter Lock (GIL) limits.
- Isolate heavy calculations using multiprocessing.
Concept Explanation
CPython manages memory using reference counting. Objects are freed immediately when their reference count drops to 0. Generational garbage collection runs periodically to clean circular references. The GIL (Global Interpreter Lock) is a lock that serializes execution, allowing only one thread to execute Python bytecode at a time.
Code Examples
Example 1 — Basics
This example introduces the fundamental syntax and concepts.
import sys
x = []
print(sys.getrefcount(x) - 1)
Example 2 — Everyday Usage
This example demonstrates a realistic scenario handling business parameters.
# Generational cyclic gc runs automatically
import gc
gc.collect() # Manually trigger cycle cleanup
Example 3 — Advanced Example
This example shows clean, production-grade code structure following senior development standards.
from multiprocessing import Process
def heavy_calc(data):
# Runs in separate process, bypassing GIL limits
return sum(x * x for x in data)
if __name__ == '__main__':
p = Process(target=heavy_calc, args=(range(1000),))
p.start()
p.join()
Visual Flow
The following execution flow represents the step-by-step evaluation inside the interpreter:
Request GIL → Run Thread Bytecode → Hit I/O or sleep timer → Release GIL → Thread switch
Common Mistakes
Review these common pitfalls when working with this topic:
- Expecting multithreading to speed up CPU-heavy tasks.
- Creating circular dependencies that delay garbage collection.
- Assuming the GIL makes application code thread-safe.
- Neglecting processing guards when launching child processes.
Best Practices
Enforce these Pythonic best practices in your codebase:
# CPU calculation multithreading
t1 = Thread(target=cpu_heavy)
t2 = Thread(target=cpu_heavy)
# CPU calculation multiprocessing
p1 = Process(target=cpu_heavy)
p2 = Process(target=cpu_heavy)
Performance Notes
Keep these optimization guidelines in mind for performance-sensitive hotpaths:
- The GIL is released during block operations like file I/O, network requests, and database queries.
- Reference counting occurs in O(1) time, while cyclic garbage collection runs periodically in O(N) time.
Quick Revision
Use these key summaries for last-minute revision:
- CPython uses reference counting to free memory.
- Cyclic GC handles self-referencing loops.
- GIL restricts concurrency of bytecodes.
- GIL is released automatically during file I/O.
- Multiprocessing utilizes separate CPU cores.