GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Add delayed reclamation mechanism for free-threaded build (QSBR) · Issue #115103 · python/cpython

Add delayed reclamation mechanism for free-threaded build (QSBR) #115103

New issue
Copy link
New issue
Copy link
Closed
Closed
Add delayed reclamation mechanism for free-threaded build (QSBR)#115103
Copy link
Assignees
colesbury
Labels
topic-free-threadingtype-featureA feature request or enhancementA feature request or enhancement

Description

@colesbury
colesbury
opened on Feb 6, 2024
Issue body actions

Feature or enhancement

Many operations in the free-threaded build are protected by locks. However, in some cases, we want to allow reads to happen concurrently with updates 1. For example, we want to avoid locking during most list read accesses. If there is a concurrent list resize operation, when is it safe to free the list's previous array?

"Safe memory reclamation" (SMR) schemes address this usually by delaying the "free" operation until all concurrent read accesses are guaranteed to have completed. Quiescent state-based reclamation (QSBR) is a safe memory reclamation scheme that will be useful in the free-threaded build. QSBR relies on marked "quiescent states", when a thread reports that it is definitely not in the middle of a non-locking read operation. The eval breaker checks serve as a good place to report a quiescent state.

Background

SMR schemes are most common in systems that don't use garbage collection or reference counting. CPython uses reference counting and has a tracing garbage collector, so it may seem like an odd fit. However, some data structures are not reference counted. For example, a list object's array is not separately reference counted, but may have a shorter lifetime than the containing PyListObject. We could delay reclamation until the GC runs, but we want reclamation to happen quickly, and we generally want to run the GC less frequently in the free-threaded build, because it requires pausing all threads and, at least for now, scanning the entire heap.

Use cases

  • Dict keys (PyDictKeysObject) and list arrays (ob_item): If we resize a dict or list that may be shared between threads, we use QSBR to delay freeing the old keys/array until it's safe to do so. Note that most dicts and lists are not accessed by multiple threads; their keys/arrays can be immediately freed on resize.
  • Mimalloc mi_page_t: The non-locking dict and list accesses require cooperation from mimalloc. We want to ensure that even if an item is freed during access and the memory reused for a new object, the new object’s reference count field is placed at the same location in memory. In practice, this means that when an mi_page_t is empty, we don't immediately allow it to be re-used for allocations of a different size class. We use QSBR to determine when it's safe to use the mi_page_t for a different size class (or return the memory to the OS).

Implementation Overview

The implementation will be partially based on FreeBSD's "Global Unbounded Sequences". The FreeBSD implementation provides a good starting point because it's relatively simple, self contained, and the license (2-Clause BSD) is compatible with CPython. The implementation relies on a few sequence counters:

  • Global (per-interpreter) write sequence: When we want to safely free a data structure, we increment the global write sequence counter and tag the data to be freed with the new value.
  • Per-thread state read sequence: When a thread reaches a quiescent state (such as when it checks the eval breaker), it copies the global write sequence to its local read counter.

It's safe to free data once all thread states' read sequences are greater than or equal to the write sequence used to tag the data.

To check that, we scan over all the thread states read sequences to compute the minimum value (excluding detached threads). For efficiency, we also cache that computed value globally (per-interpreter).

Limitations

Determining the current minimum read sequence requires scanning over all thread states. This will likely become a bottleneck if we have a large number of threads (>1,000?). We will likely eventually want to address this, possibly with some combination of a tree-based mechanism 2 and incremental scanning.

For now, I think keeping the implementation simple important until we are able to run and benchmark multithreaded programs with the GIL disabled.

Linked PRs

  • gh-115103: Implement delayed memory reclamation (QSBR) #115180
  • gh-115103: Implement delayed free mechanism for free-threaded builds #115367
  • gh-115103: Delay reuse of mimalloc pages that store PyObjects #115435
  • gh-115103: Update gc.collect to process delayed objects #116238
  • gh-115103: Update gc.collect to process delayed objects #116251
  • gh-115103: Enable internal mimalloc assertions in debug builds #116343
  • gh-115103: Fix unregistering of QSBR state #116480

Footnotes

  1. See "Optimistically Avoiding Locking" in PEP 703. ↩

  2. https://people.kernel.org/joelfernandes/gus-vs-rcu ↩

Activity

Next
  1. colesbury
    added
    type-featureA feature request or enhancementA feature request or enhancement
    topic-free-threading
    on Feb 6, 2024
  2. colesbury
    self-assigned this
    on Feb 6, 2024
  3. colesbury
    added 12 commits that reference this issue on Feb 7, 2024

    pythongh-115103: Implement delayed memory reclamation (QSBR)

    cbfc9a5

    pythongh-115103: Implement delayed memory reclamation (QSBR)

    a99d214

    pythongh-115103: Implement delayed memory reclamation (QSBR)

    ede08ee

    Merge branch 'main' into pythongh-115103-qsbr

    35cbc0e

    pythongh-115103: Implement delayed free mechanism for free-threaded b…

    a661366

    pythongh-115103: Delay reuse of mimalloc pages that store PyObjects

    e3489f6

    pythongh-115103: Implement delayed free mechanism for free-threaded b…

    856bba3

    pythongh-115103: Delay reuse of mimalloc pages that store PyObjects

    3c3133b

    Merge branch 'main' into pythongh-115103-qsbr

    c0034b7

    Merge branch 'main' into pythongh-115103-qsbr

    b03c5ca

    Merge branch 'main' into pythongh-115103-qsbr

    be441dc

    gh-115103: Implement delayed memory reclamation (QSBR) (#115180)

    5903190
  4. 29 remaining items

  5. adorilson
    added 2 commits that reference this issue on Mar 25, 2024

    pythongh-115103: Delay reuse of mimalloc pages that store PyObjects (p…

    ef3e9f5

    pythongh-115103: Fix unregistering of QSBR state (python#116480)

    e4920cb
  6. diegorusso
    added 7 commits that reference this issue on Apr 17, 2024

    pythongh-115103: Implement delayed memory reclamation (QSBR) (python#…

    1c8ae9d

    pythongh-115103: Implement delayed free mechanism for free-threaded b…

    b445298

    pythongh-115103: Update refleak checker to trigger _PyMem_ProcessDela…

    4b11f2d

    pythongh-115103: Update gc.collect to process delayed objects (python…

    dd1b844

    pythongh-115103: Enable internal mimalloc assertions in debug builds (p…

    a78f2c0

    pythongh-115103: Delay reuse of mimalloc pages that store PyObjects (p…

    8757509

    pythongh-115103: Fix unregistering of QSBR state (python#116480)

    27fc3e3
  7. LukasWoodtli
    added 2 commits that reference this issue on Jan 22, 2025

    pythongh-115103: Implement delayed memory reclamation (QSBR) (python#…

    2a9ba46

    pythongh-115103: Implement delayed free mechanism for free-threaded b…

    bdbaa84
  8. corona10
    added 2 commits that reference this issue on Oct 10, 2026

    Re-apply CPython-specific changes to mimalloc v2.5.2

    fa3a143

    Re-apply CPython-specific changes to mimalloc v2.5.2

    836dced
  9. corona10
    added 2 commits that reference this issue on Oct 22, 2026

    gh-159111: Update vendored mimalloc to v2.5.2 (gh-159112)

    aff7a2e

    [3.15] pythongh-159111: Update vendored mimalloc to v2.5.2 (pythongh-…

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

Metadata

Metadata

Assignees

  • @colesbury
    colesbury

Labels

topic-free-threadingtype-featureA feature request or enhancementA feature request or enhancement

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    You are visitor 01402503 — GeezerVison does not store the pages you look up.
    Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.