Skip to content

GH-157724: Fix typos in InternalDocs/garbage_collector.md (and in gc.c and gc_free_threading.c comments, NO code changes) - #157879

Open
willy-b wants to merge 6 commits into
python:mainfrom
willy-b:fix-gh-157724-squash
Open

willy-b wants to merge 6 commits into
python:mainfrom
willy-b:fix-gh-157724-squash

Conversation

@willy-b

@willy-b willy-b commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

(no AI or LLMs were used in discovering the typos or preparing these changes)

This should not be backported (at least without modification, to any version prior to v3.14 as it references content that is specific to that version or later, e.g. ob_flags replacing the padding field in the object headers).

Footnotes

  1. ."LIFO stack, of unlimited size" used during mark alive free threaded build GC phase: https://github.com/python/cpython/blob/5539c2a5437acc4f4719aabac375368e0d310bd9/InternalDocs/garbage_collector.md?plain=1#L536 ↩

  2. .vs. "the objects themselves contain all the storage the GC algorithms require" https://github.com/python/cpython/blob/5539c2a5437acc4f4719aabac375368e0d310bd9/InternalDocs/garbage_collector.md?plain=1#L301 (may be true for the non-free threaded build only, for gc.c NOT gc_free_threading.c ; though "neither does it in any other way require additional memory proportional to the number of objects" is still possibly misleading as adding per object overhead still requires memory proportional to the number of objects and is not necessarily more scalable than externalizing that cost to a separate data structure.) ↩ ↩2

  3. ."nearly all objects that are not actually unreachable" are visited during the mark alive free threaded build GC phase: https://github.com/python/cpython/blob/e2ff498cc03886b73fca0429ee745b04646ad8e0/Python/gc_free_threading.c#L1363 ↩ ↩2

  4. ._PyObjectStack_Pop is used by gc_propagate_alive, e.g. at https://github.com/python/cpython/blob/e2ff498cc03886b73fca0429ee745b04646ad8e0/Python/gc_free_threading.c#L1346 ; also after the mark alive stage too at e.g. mark_reachable https://github.com/python/cpython/blob/41d09220bda74cda6897a4e807d7af0edaff1fd8/Python/gc_free_threading.c#L1048 ↩

  5. ._PyObjectStack_Push is used by gc_propagate_alive, e.g. at https://github.com/python/cpython/blob/e2ff498cc03886b73fca0429ee745b04646ad8e0/Python/gc_free_threading.c#L705 ; also after the mark alive stage too at e.g. visit_clear_unreachable https://github.com/python/cpython/blob/41d09220bda74cda6897a4e807d7af0edaff1fd8/Python/gc_free_threading.c#L1032 . ↩

  6. . _PyObjectStack_Push seems to allocate fresh memory, not reuse pointers already on the "objects themselves": https://github.com/python/cpython/blob/e2ff498cc03886b73fca0429ee745b04646ad8e0/Include/internal/pycore_object_stack.h#L37-L48 ; and see also gc_mark_span_push https://github.com/python/cpython/blob/e2ff498cc03886b73fca0429ee745b04646ad8e0/Python/gc_free_threading.c#L666-L678 ↩

  7. in other places in the same section distinctions are made between the free threaded and non-free threaded GCs, e.g. at https://github.com/python/cpython/blob/5539c2a5437acc4f4719aabac375368e0d310bd9/InternalDocs/garbage_collector.md?plain=1#L229 but not for this paragraph ↩

…in gc_free_threading.c comments, NO code changes)

(no AI or LLMs were used in discovering the typos or preparing these changes)

- Typo fixes for a few items in InternalDocs/garbage_collector.md
  - At https://github.com/python/cpython/blob/5539c2a5437acc4f4719aabac375368e0d310bd9/InternalDocs/garbage_collector.md?plain=1#L619
    "6 GB L2" should be "6 MB L2"  (describing AMD Ryzen 5 7600X L2 cache size, see https://web.archive.org/web/20260918004211/https://www.amd.com/en/products/processors/desktops/ryzen/7000-series/amd-ryzen-5-7600x.html for reference)
  - At https://github.com/python/cpython/blob/5539c2a5437acc4f4719aabac375368e0d310bd9/InternalDocs/garbage_collector.md?plain=1#L451
    "<constant number>" should be "constant number" so that it is not hidden in markdown display
  - At https://github.com/python/cpython/blob/5539c2a5437acc4f4719aabac375368e0d310bd9/InternalDocs/garbage_collector.md?plain=1#L536
    "prefech" should be "prefetch" ; I also replaced "LIFO stack, of unlimited size" with "LIFO stack, limited only by available memory" (e.g. https://github.com/python/cpython/blob/a64b7ecba4db5480504a1a83ae6e80c81472fe16/Python/gc_free_threading.c#L1426 , https://github.com/python/cpython/blob/a64b7ecba4db5480504a1a83ae6e80c81472fe16/Python/gc_free_threading.c#L826-L831 , before https://github.com/python/cpython/blob/a64b7ecba4db5480504a1a83ae6e80c81472fe16/Python/gc_free_threading.c#L2116 )

- Typo fixes for 2x "contigous" (in comments, in gc_free_threading.c - NO code/functionality changes):
  https://github.com/python/cpython/blob/a64b7ecba4db5480504a1a83ae6e80c81472fe16/Python/gc_free_threading.c#L579
  and
  https://github.com/python/cpython/blob/a64b7ecba4db5480504a1a83ae6e80c81472fe16/Python/gc_free_threading.c#L749

- Propose to remove a seemingly outdated (not applicable to e.g. mark alive phase of free-threaded Python builds), potentially confusing paragraph

  **In the free-threaded build**  ( https://peps.python.org/pep-0703/ , https://peps.python.org/pep-0779/ )
  already discussed in many places in this article,
  the "LIFO stack, of unlimited size"[^0] mentioned seems to not use the existing pointers on "the objects themselves"[^5],
  e.g. in `gc_propagate_alive` (of which it is said "In most programs, this marks nearly all objects that are not actually unreachable"[^1])
  `_PyObjectStack_Pop`[^2]
  and `_PyObjectStack_Push`[^3]
  are used,
  and the push seems to allocate fresh memory[^4]
  https://github.com/python/cpython/blob/e2ff498cc03886b73fca0429ee745b04646ad8e0/Include/internal/pycore_object_stack.h#L37-L48 (for one simple case to consider, in the free threaded build with prefetch disabled,
  the `gc_propagate_alive` appears to be a DFS of "nearly all objects that are not actually unreachable"[^1] so would seem to have worst case O(n) additional memory requirements -- contrary to "neither does it in any other way require additional memory proportional to the
  number of objects"[^5]).

  Thus I propose to remove a paragraph on O(1) space usage, "no additional memory proportional to the number of objects" in its current form as potentially confusing.
  ( https://github.com/python/cpython/blob/5539c2a5437acc4f4719aabac375368e0d310bd9/InternalDocs/garbage_collector.md?plain=1#L299 )

  (it might still be descriptive of some configuration of the non-free threaded GC[^6], to gc.c instead of gc_free_threading.c,
   only if the doubly linked list pointers used for all traversals in that implementation are built into the objects in advance,
  _with the caveat that adding overhead to each object, instead of externalizing it to a separate stack, still requires memory proportional to the number of objects_.
  Note also comments at https://github.com/python/cpython/blob/a64b7ecba4db5480504a1a83ae6e80c81472fe16/Python/gc_free_threading.c#L1192-L1193 , and

    https://github.com/python/cpython/blob/a64b7ecba4db5480504a1a83ae6e80c81472fe16/Misc/NEWS.d/3.13.0a4.rst?plain=1#L150-L153 )

- Add a note in two places where something is specific to the non-free-threaded build
  - At https://github.com/python/cpython/blob/41d09220bda74cda6897a4e807d7af0edaff1fd8/InternalDocs/garbage_collector.md?plain=1#L285
    note "PREV_MASK_COLLECTING" is the name of the flag used in the non-free-threaded build
  - At https://github.com/python/cpython/blob/41d09220bda74cda6897a4e807d7af0edaff1fd8/InternalDocs/garbage_collector.md?plain=1#L634 ,
    note the "fat pointer"/"tagged pointer" memory saving techniques applied to the two linked list pointers discussed in that section are specific to the non-free-threaded build

  References:
  [^0]: ."LIFO stack, of unlimited size" used during mark alive free threaded build GC phase: https://github.com/python/cpython/blob/5539c2a5437acc4f4719aabac375368e0d310bd9/InternalDocs/garbage_collector.md?plain=1#L536
  [^1]: ."nearly all objects that are not actually unreachable" are visited during the mark alive free threaded build GC phase: https://github.com/python/cpython/blob/e2ff498cc03886b73fca0429ee745b04646ad8e0/Python/gc_free_threading.c#L1363
  [^2]: ._PyObjectStack_Pop  is used by gc_propagate_alive, e.g. at https://github.com/python/cpython/blob/e2ff498cc03886b73fca0429ee745b04646ad8e0/Python/gc_free_threading.c#L1346 ; also after the mark alive stage too at e.g. mark_reachable https://github.com/python/cpython/blob/41d09220bda74cda6897a4e807d7af0edaff1fd8/Python/gc_free_threading.c#L1048
  [^3]: ._PyObjectStack_Push  is used by gc_propagate_alive, e.g. at https://github.com/python/cpython/blob/e2ff498cc03886b73fca0429ee745b04646ad8e0/Python/gc_free_threading.c#L705 ; also after the mark alive stage too at e.g. visit_clear_unreachable https://github.com/python/cpython/blob/41d09220bda74cda6897a4e807d7af0edaff1fd8/Python/gc_free_threading.c#L1032 .
  [^4]: . _PyObjectStack_Push seems to allocate fresh memory, not reuse pointers already on the "objects themselves": https://github.com/python/cpython/blob/e2ff498cc03886b73fca0429ee745b04646ad8e0/Include/internal/pycore_object_stack.h#L37-L48 ; and see also `gc_mark_span_push` https://github.com/python/cpython/blob/e2ff498cc03886b73fca0429ee745b04646ad8e0/Python/gc_free_threading.c#L666-L678
  [^5]: .vs. "the objects themselves contain all the storage the GC algorithms require" https://github.com/python/cpython/blob/5539c2a5437acc4f4719aabac375368e0d310bd9/InternalDocs/garbage_collector.md?plain=1#L301 (may be true for the non-free threaded build only, for gc.c NOT gc_free_threading.c  ; though "neither does it in any other way require additional memory proportional to the number of objects" is still possibly misleading as adding per object overhead still requires memory proportional to the number of objects and is not necessarily more scalable than externalizing that cost to a separate data structure.)
  [^6]:  in other places in the same section distinctions are made between the free threaded and non-free threaded GCs, e.g. at https://github.com/python/cpython/blob/5539c2a5437acc4f4719aabac375368e0d310bd9/InternalDocs/garbage_collector.md?plain=1#L229 but not for this paragraph
@willy-b willy-b changed the title GH-157724: Fix typos in InternalDocs/garbage_collector.md (and in gc_free_threading.c comments, NO code changes) GH-157724: Fix typos in InternalDocs/garbage_collector.md (and in gc.c and gc_free_threading.c comments, NO code changes) Sep 21, 2026
…e changes)

- Fix a typo in a comment in gc.c (NO code changes)
  "generation" to "generations" at https://github.com/python/cpython/blob/212e6035133957a66f1a823e012b4dc2a5158ce8/Python/gc.c#L516
- In garbage_collector.md
  - note "Why moving unreachable objects is better" applies only to the non-free-threaded build (update https://github.com/python/cpython/blob/212e6035133957a66f1a823e012b4dc2a5158ce8/InternalDocs/garbage_collector.md?plain=1#L304 )
  - note that objects do not move to/from an unreachable list in the free-threaded build (the _PyGC_BITS_UNREACHABLE ob_gc_bits flag is set)
  - remove "This process is really a breadth first search over the object graph" regarding propagating reachable status from objects found to be reachable as it is not so simple
    e.g. on the free-threaded build, for each object during the heap traversal found to be reachable within the unreachable flagged items,
    it seems a new depth-first (not breadth-first) search is initiated to propagate the reachability status
    see  https://github.com/python/cpython/blob/212e6035133957a66f1a823e012b4dc2a5158ce8/Python/gc_free_threading.c#L1461 , mark_heap_visitor , calls gc_clear_unreachable then
    mark_reachable (important)
    https://github.com/python/cpython/blob/212e6035133957a66f1a823e012b4dc2a5158ce8/Python/gc_free_threading.c#L1039 which seems to use a stack to do a DFS https://github.com/python/cpython/blob/212e6035133957a66f1a823e012b4dc2a5158ce8/Python/gc_free_threading.c#L1032 , https://github.com/python/cpython/blob/212e6035133957a66f1a823e012b4dc2a5158ce8/Python/gc_free_threading.c#L1048
@willy-b

willy-b commented Sep 22, 2026

Copy link
Copy Markdown
Contributor Author

(Note this branch will show checks failing until someone marks this with the "skip news" label (I don't have permission at least in the Github interface).)

- Replace "pad" field with "ob_flags":
  At python@bc262de#diff-87272721a5cf1cd9915d6f503f6a7bbefa2f26c935c7ce83ca78706afd0ad05aR155
  it seems _padding was replaced with ob_flags as part of python#127797

- Add backticks around some new mentions of flag and field names to be consistent in styling
@read-the-docs-community

Copy link
Copy Markdown

Documentation build overview

📚 cpython-previews | 🛠️ Build #34725421 | 📁 Comparing 7f9b890 against main (b54ae4c)

  🔍 Preview build  

1 file changed
± library/gc.html

@willy-b

willy-b commented Sep 23, 2026

Copy link
Copy Markdown
Contributor Author

Note a second change to update gc.rst links to a pinned version of garbage_collector.md will be required after this merges (yielding a new revision we can pin there), at e.g.

see `Collecting the oldest generation <https://github.com/python/cpython/blob/ff0ef0a54bef26fc507fbf9b7a6009eb7d3f17f5/InternalDocs/garbage_collector.md#collecting-the-oldest-generation>`_ for more information.
as we would want to update those to point to the version with these changes only once these merge into main.

Also, a caveat:
This PR #157879 concerns InternalDocs/garbage_collector.md which was reviewed in order to find the items fixed (mostly just brought up to date) here. However, there may still be additional aspects that are out of date -- if I find them, I will send a follow up PR, but in a first pass, these are what I find and it is a review sized batch of updates that I am confident are needed (to improve accuracy for readers) so I am sending them.
Only one item is reviewed from Doc/library/gc.rst in this PR that was found to be out of date and inconsistent with InternalDocs/garbage_collector.md but that article may have further items needing to be brought up to date. Other GC related documentation, e.g. Doc/c-api/gcsupport.rst , Doc/c-api/refcounting.rst WERE NOT reviewed at all yet in preparing this and are not covered by this PR. I may review them soon.

@willy-b

willy-b commented Nov 2, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @pablogsal in advance for a review on this one, let me know if you are waiting on anything else from me before this is review-ready (no pressure, take any amount of time, was just checking this since it has been over a month, and wanted to make sure it wasn't blocked on something I don't know about).

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants