CPython’s Memory Engine: Allocation, Deallocation, and Free-List Tricks
- Track:
- Python Core, Internals, Extensions
- Type:
- Talk (long session)
- Level:
- intermediate
- Duration:
- 45 minutes
Abstract
This talk is a practical tour of how CPython really manages memory: from obj = SomeClass() to the moment its bytes are reused or released back to the OS.
We’ll start with the basics: object layout, refcounts, and how CPython’s small-object allocator (pymalloc) hands out memory in arenas and pools instead of calling malloc for every tiny object. You’ll see what actually happens when you create lots of ints, tuples, and short-lived objects in hot loops.
Then we’ll simplify the lifecycle on the way out: what happens when a refcount hits zero, how CPython runs type-specific deallocation code and optional finalizers, and how user del fits into that chain. We’ll look at how memory is either returned to the allocator or kept on freelists to be reused quickly, and why this can look like a “leak” from the outside.
In the second half, we’ll focus on optimisations and allocator swaps. We’ll look at freelists for ints, tuples, frames, and other core objects: why they exist, how they speed up hot paths, and when they keep memory around longer than you expect. Then we’ll compare pymalloc with mimalloc: how they differ in fragmentation, multithread behaviour, what actually changes when you run Python with mimalloc, and how to measure the impact with simple benchmarks and tracemalloc-style tooling.
You’ll leave with a clear mental model of CPython’s (de)allocation pipeline, an intuition for what freelists and alternative allocators are really doing.