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 — [3.14] gh-149242: Heap size should be added at end of the struct by DinoV · Pull Request #149241 · python/cpython

Conversation

@DinoV

@DinoV DinoV commented May 1, 2026 •
edited by bedevere-app Bot
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

The offset of _gc_runtime_state is exported via the debug offsets, but only offset within it is exported. It's likely that someone could be doing something slimey like looking at other fields. init. It's probably best to only add things to the end rather than change the offsets of existing members of the struct in a patch release.

  • Issue: Modifying offsets of existing members in _gc_runtime_state is probably a bad idea #149242

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@DinoV DinoV added the skip news label May 1, 2026
@DinoV DinoV changed the title gh-149025: Heap size should be added at end of the struct [3.14] gh-149242: Heap size should be added at end of the struct May 1, 2026
@bedevere-app bedevere-app Bot mentioned this pull request May 1, 2026
Modifying offsets of existing members in _gc_runtime_state is probably a bad idea #149242
Closed
@DinoV
Move heap_size to end of struct
0a85f88
@DinoV
DinoV force-pushed the heap_size branch from 7fcc068 to 0a85f88 Compare May 1, 2026 16:37
@DinoV
DinoV requested review from hugovk and sergey-miryanov May 1, 2026 16:37
@read-the-docs-community

read-the-docs-community Bot commented May 1, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

Documentation build overview

📚 cpython-previews | 🛠️ Build #32502172 | 📁 Comparing 4caf7b6 against main (9668d26)

  🔍 Preview build  

412 files changed · ± 398 modified · - 14 deleted

± Modified

  • about.html
  • bugs.html
  • contents.html
  • download.html
  • genindex-A.html
  • genindex-B.html
  • genindex-C.html
  • genindex-D.html
  • genindex-E.html
  • genindex-F.html
  • and 388 more...

- Deleted

  • _static/tachyon-example-flamegraph.html
  • _static/tachyon-example-heatmap.html
  • c-api/sentinel.html
  • deprecations/c-api-pending-removal-in-3.19.html
  • deprecations/c-api-pending-removal-in-3.20.html
  • deprecations/pending-removal-in-3.20.html
  • deprecations/soft-deprecations.html
  • extending/first-extension-module.html
  • library/math.integer.html
  • library/profiling.html
  • and 4 more...
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

sergey-miryanov
sergey-miryanov approved these changes May 1, 2026
View reviewed changes

@sergey-miryanov sergey-miryanov left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! It looks good to me.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@bedevere-app bedevere-app Bot added the awaiting core review label May 1, 2026
@sergey-miryanov sergey-miryanov mentioned this pull request May 1, 2026
GH-148726: Add heap_size to generational GC #149195
Merged
@DinoV
DinoV marked this pull request as ready for review May 1, 2026 16:59
@DinoV
DinoV requested a review from encukou as a code owner May 1, 2026 16:59
itamaro
itamaro approved these changes May 1, 2026
View reviewed changes

@itamaro itamaro left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks!

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@bedevere-app bedevere-app Bot added awaiting merge and removed awaiting core review labels May 1, 2026
@nascheme

nascheme commented May 1, 2026 •
edited by hugovk
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

Not modifying the offsets of existing members seems prudent, can't really hurt. However, I think since we have changed other members of the struct, we need to have a different patch, the recent changes to this struct are as follows:

 struct _gc_runtime_state {
     /* List of objects that still need to be cleaned up, singly linked
      * via their gc headers' gc_prev pointers.  */
     PyObject *trash_delete_later;
     /* Current call-stack depth of tp_dealloc calls. */
     int trash_delete_nesting;
 
     /* Is automatic collection enabled? */
     int enabled;
     int debug;
     /* linked lists of container objects */
+#ifndef Py_GIL_DISABLED
+    struct gc_generation generations[NUM_GENERATIONS];
+    PyGC_Head *generation0;
+#else
     struct gc_generation young;
     struct gc_generation old[2];
+#endif
     /* a permanent generation which won't be collected */
     struct gc_generation permanent_generation;
     struct gc_generation_stats generation_stats[NUM_GENERATIONS];
     /* true if we are currently running the collector */
     int collecting;
     /* list of uncollectable objects */
     PyObject *garbage;
     /* a list of callbacks to be invoked when collection is performed */
     PyObject *callbacks;
 
+    /* The number of live objects. */
     Py_ssize_t heap_size;
-    Py_ssize_t work_to_do;
-    /* Which of the old spaces is the visited space */
-    int visited_space;
-    int phase;
 
-#ifdef Py_GIL_DISABLED
     /* This is the number of objects that survived the last full
        collection. It approximates the number of long lived objects
        tracked by the GC.
 
        (by "full collection", we mean a collection of the oldest
        generation). */
     Py_ssize_t long_lived_total;
     /* This is the number of objects that survived all "non-full"
        collections, and are awaiting to undergo a full collection for
        the first time. */
     Py_ssize_t long_lived_pending;
 
+#ifdef Py_GIL_DISABLED
     /* True if gc.freeze() has been used. */
     int freeze_active;
 
     /* Memory usage of the process (RSS + swap) after last GC. */
     Py_ssize_t last_mem;
 
     /* This accumulates the new object count whenever collection is deferred
        due to the RSS increase condition not being meet.  Reset on collection. */
     Py_ssize_t deferred_count;
 
     /* Mutex held for gc_should_collect_mem_usage(). */
     PyMutex mutex;
 #endif
 };

I would think we want something like the following, to preserve as many offsets as we can:

--- a/Include/internal/pycore_interp_structs.h
+++ b/Include/internal/pycore_interp_structs.h
@@ -210,13 +210,10 @@ struct _gc_runtime_state {
     int enabled;
     int debug;
     /* linked lists of container objects */
-#ifndef Py_GIL_DISABLED
-    struct gc_generation generations[NUM_GENERATIONS];
-    PyGC_Head *generation0;
-#else
+    /* Note this is only used for the Py_GIL_DISABLED build, retained to preserve
+     * other member offsets. */
     struct gc_generation young;
     struct gc_generation old[2];
-#endif
     /* a permanent generation which won't be collected */
     struct gc_generation permanent_generation;
     struct gc_generation_stats generation_stats[NUM_GENERATIONS];
@@ -230,6 +227,11 @@ struct _gc_runtime_state {
     /* The number of live objects. */
     Py_ssize_t heap_size;
 
+    /* dummy members to preserve other offsets */
+    Py_ssize_t dummy1; /* was work_to_do */
+    int dummy2; /* was visited_space */
+    int dummy3; /* was phase */
+
     /* This is the number of objects that survived the last full
        collection. It approximates the number of long lived objects
        tracked by the GC.
@@ -255,6 +257,10 @@ struct _gc_runtime_state {
 
     /* Mutex held for gc_should_collect_mem_usage(). */
     PyMutex mutex;
+#else
+    /* linked lists of container objects */
+    struct gc_generation generations[NUM_GENERATIONS];
+    PyGC_Head *generation0;
 #endif
 };
DinoV reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@sergey-miryanov

sergey-miryanov commented May 1, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

@nascheme We could use young and old for the generational GC as well, and drop generation0 too. WDYT?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@DinoV

DinoV commented May 1, 2026

Copy link
Copy Markdown
Contributor Author

@nascheme We could use young and old for the generational GC as well, and drop generation0 too. WDYT?

We could keep the array on the GIL disabled build and just move generation0 to the end.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@DinoV
Maximize compatibility w/ 3.14.3
1d5015e
@sergey-miryanov

sergey-miryanov commented May 1, 2026

Copy link
Copy Markdown
Contributor

generation0 used a little. Initialized as gcstate->generation0 = GEN_HEAD(gcstate, 0); and used only in _PyObject_GC_TRACK.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@DinoV
ABI updates
4caf7b6
hugovk
hugovk approved these changes May 1, 2026
View reviewed changes
@DinoV

DinoV commented May 1, 2026

Copy link
Copy Markdown
Contributor Author

Final version incorporates Neil's suggestion of adding the dummy fields and keeping heap_size where it was at and moving generation0 to the end but keeps the gc_generation where it was at because it's size hasn't changed.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@DinoV
DinoV merged commit 312a596 into python:3.14 May 1, 2026
48 checks passed

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-app bedevere-app Bot removed the awaiting merge label May 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@sergey-miryanov sergey-miryanov sergey-miryanov approved these changes
@itamaro itamaro itamaro approved these changes
@hugovk hugovk hugovk approved these changes
@encukou encukou Awaiting requested review from encukou encukou is a code owner

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

skip news

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

5 participants

@DinoV @nascheme @sergey-miryanov @itamaro @hugovk
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.