Skip to content

Use stackrefs in _PyType_LookupRef and related functions #131586

Closed
@colesbury

Description

@colesbury

Feature or enhancement

The object_lookup_special microbenchmark in Tools/ftscalingbench/ftscalingbench.py currently doesn't scale well and is indicative of a broader FT performance issue that we should fix. The benchmark just calls round() from multiple threads concurrently:

def object_lookup_special():
# round() uses `_PyObject_LookupSpecial()` internally.
N = 1000 * WORK_SCALE
for i in range(N):
round(i / N)

The issue is that round() calls _PyObject_LookupSpecial(number, &_Py_ID(__round__)), which increments the reference count of the returned function (i.e., of float.round). The underlying function supports deferred reference counting, but _PyObject_LookupSpecial and _PyType_LookupRef do not take advantage of it.

For the FT build, we also need some extra support in order to safely use _PyStackRef in builtin_round_impl, because it's important that all _PyStackRefs are visible to the GC. To support this, we can add a singly linked list of active _PyStackRefs to _PyThreadStateImpl.

The struct _PyCStackRef implements this linked list pointer + a _PyStackRef. In the GIL-enabled build, there's no linked list and it's essentially the same as _PyStackRef.

/ A stackref that can be stored in a regular C local variable and be visible
/ to the GC in the free threading build.
/ Used in combination with _PyThreadState_PushCStackRef().
typedef struct _PyCStackRef {
    _PyStackRef ref;
#ifdef Py_GIL_DISABLED
    struct _PyCStackRef *next;
#endif
} _PyCStackRef;

struct _PyThreadStateImpl {
    ...
    / Linked list (stack) of active _PyCStackRef
    struct _PyCStackRef *c_stack_refs;
    ...
}

static inline void _PyThreadState_PushCStackRef(PyThreadState *tstate, _PyCStackRef *ref) { ... }
static inline void _PyThreadState_PopCStackRef(PyThreadState *tstate, _PyCStackRef *ref) { ... }

cc @mpage @markshannon

Linked PRs

Activity

added a commit that references this issue on Mar 22, 2025

pythongh-131586: Avoid refcount contention in some "special" calls

added 2 commits that reference this issue on Mar 26, 2025

gh-131586: Avoid refcount contention in some "special" calls (#131588)

67fbfb4

pythongh-131586: Avoid refcount contention in context managers

added a commit that references this issue on Mar 28, 2025
added a commit that references this issue on Apr 1, 2025

pythongh-131586: Avoid refcount contention in some "special" calls (p…

added 2 commits that reference this issue on Apr 4, 2025
added a commit that references this issue on Apr 16, 2025

pythongh-131586: Avoid refcount contention in some "special" calls (p…

added 2 commits that reference this issue on Apr 16, 2025

2 remaining items

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Use stackrefs in `_PyType_LookupRef` and related functions · Issue #131586 · python/cpython

      Follow Lee on X/Twitter - Father, Husband, Serial builder creating AI, crypto, games & web tools. We are friends :) AI Will Come To Life!

      Check out: eBank.nz (Art Generator) | Netwrck.com (AI Tools) | Text-Generator.io (AI API) | BitBank.nz (Crypto AI) | ReadingTime (Kids Reading) | RewordGame | BigMultiplayerChess | WebFiddle | How.nz | Helix AI Assistant