python / cpython

The Python programming language
https://www.python.org/
Other
60.94k stars 29.41k forks source link

Deferred reference counts #120024

Open markshannon opened 1 month ago

markshannon commented 1 month ago

Feature or enhancement

Proposal:

Approximately 80% of reference count operations occur in the interpreter. stats The vast majority of these operations are needed only to maintain the correct reference counts for references in local variables and the evaluation stack. We should not count these references, instead deferring them until we wish to perform incremental collection.

Doing so will give us a reasonable speedup on default builds, but the real value is for free-threading. Free-threading requires that some references on the frame stack are deferred, but tagging those references is expensive. It is much more efficient to simply deferred all references on the frame stack.

This is not a new idea, in fact it is a very old one.

The implementation is conceptually fairly simple:

Like many "simple" ideas, the devil is in the detail.

There are two main concerns:

We can keep reclamation acceptably prompt, by tracking the size of objects in the Zero Count Table, the size of objects allocated. Once this number gets large enough, we perform a collection at the next opportunity.

We can keep the overhead of updating the reference counts low, by only deferring the top of the stack. Parts of the stack that are not accessed between collections, can be counted eagerly, reducing the amount of scanning needed to a few frames.

Previous discussion

https://github.com/faster-cpython/ideas/issues/677

markshannon commented 1 month ago

https://github.com/python/cpython/issues/119866 shows that it is possible to keep all stack pointers reachable in memory whenever execution escapes from the interpreter. This means that we make reclamation as prompt as want.