Recent Optimizations in Python's Reference Counting

https://news.ycombinator.com/rss Hits: 2
Summary

It's been a while since I've written about CPython internals and its optimizations. My last article on garbage collection was written 8 years ago. A lot of small optimizations were added since then. In this article, I will highlight a new optimization for reference counting that uses a static lifetime analysis. Background on reference counting in CPython Reference counting is the primary memory management technique used in CPython. In short, every Python object (the actual value behind a variable) has a reference counter field that tracks how many references point to it. When an object's reference count drops to zero, the memory occupied by that object is immediately deallocated. For hot loops, this can lead to significant overhead due to the frequent incrementing and decrementing of reference counts. The counter must be updated whenever an object is referenced or dereferenced, which hurts performance and trashes CPU caches. So, when you read a variable in Python, you actually write to the memory as well. For more details, you can read my article on garbage collection. New bytecode instruction Since Python 3.14, there is a new bytecode instruction called LOAD_FAST_BORROW. This is an optimized instruction that avoids incrementing the reference count when loading local variables. Let's look at this simple function: def advance(vx, vy, steps): x, y = 1, 1 for _ in range(steps): x *= vx y *= vy return x, y Since we check the value of vx and vy every iteration, their reference counts are incremented and decremented repeatedly. Now, let's look at the bytecode output for different Python versions. Python 3.13: 7 RESUME 0 8 LOAD_CONST 1 ((1, 1)) UNPACK_SEQUENCE 2 STORE_FAST_STORE_FAST 52 (x, y) 9 LOAD_GLOBAL 1 (range + NULL) LOAD_FAST 2 (steps) CALL 1 GET_ITER L1: FOR_ITER 11 (to L2) STORE_FAST 5 (_) 10 LOAD_FAST_LOAD_FAST 48 (x, vx) BINARY_OP 18 (*=) STORE_FAST 3 (x) 11 LOAD_FAST_LOAD_FAST 65 (y, vy) BINARY_OP 18 (*=) STORE_FAST 4 (y) JUMP_BACKWARD 13 (to L1) 9 L2: END_FOR...

First seen: 2026-01-09 01:49

Last seen: 2026-01-09 02:49