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 — gh-111968: Introduce _PyFreeListState and _PyFreeListState_GET API by corona10 · Pull Request #113584 · python/cpython

Conversation

@corona10

@corona10 corona10 commented Dec 30, 2023 •
edited by bedevere-app Bot
Loading

Uh oh!

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

Copy link
Copy Markdown
Member
  • Issue: Use per-thread freelists in --disable-gil builds #111968

Sorry, something went wrong.

Uh oh!

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

All reactions
@corona10 corona10 added the skip news label Dec 30, 2023
@bedevere-app bedevere-app Bot mentioned this pull request Dec 30, 2023
Use per-thread freelists in --disable-gil builds #111968
Closed
@corona10 corona10 added DO-NOT-MERGE topic-free-threading labels Dec 30, 2023
@corona10
pythongh-111968: Introduce _Py_freelist_state and _PyFreeListState_GE…
cd4863c
…T API
@corona10
corona10 force-pushed the gh-111968 branch from 6acf43d to cd4863c Compare December 30, 2023 15:00
@corona10

corona10 commented Dec 30, 2023 •
edited
Loading

Uh oh!

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

Copy link
Copy Markdown
Member Author
  • This PR introduces _PyFreeListState and a _PyFreeListState_GET function to seamlessly manage free-lists for 2 versions of CPython (default / free-threading).
    • Runtime authors do not need to consider where the free list is positioned. (Except for gc author ;) )
  • Zero impact change on the default CPython build
    • It will be managed as per-interpreter free list as same as before.
  • This PR is modified commit 88ec919 of @colesbury
  • Only apply for the free-list of list as the minimal work (the rest of things will be changed with separated PRs).
All reactions

Sorry, something went wrong.

Uh oh!

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

corona10 added 3 commits December 31, 2023 00:06
@corona10
nit
333873d
@corona10
Remove comment
8b7e261
@corona10
Update _PyList_Fini
dd0afa2
@corona10 corona10 removed the DO-NOT-MERGE label Dec 30, 2023
@corona10
corona10 requested review from DinoV and colesbury December 30, 2023 15:47
@corona10
corona10 marked this pull request as ready for review December 30, 2023 15:47
@corona10
corona10 requested a review from pablogsal as a code owner December 30, 2023 15:47
@bedevere-app bedevere-app Bot added the awaiting core review label Dec 30, 2023
@corona10 corona10 changed the title gh-111968: Introduce _Py_freelist_state and _PyFreeListState_GET API gh-111968: Introduce Py_freelist_state and _PyFreeListState_GET API Dec 30, 2023
@corona10 corona10 changed the title gh-111968: Introduce Py_freelist_state and _PyFreeListState_GET API gh-111968: Introduce PyFreeListState and _PyFreeListState_GET API Dec 30, 2023
corona10
corona10 commented Dec 31, 2023
View reviewed changes
Comment thread Modules/gcmodule.c Resolved

Uh oh!

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

corona10 added 2 commits December 31, 2023 13:28
@corona10
nit refactor
f0d55de
@corona10
fix
5e8e3b4
corona10
corona10 commented Dec 31, 2023
View reviewed changes
Comment thread Modules/gcmodule.c Outdated

static void
clear_freelists(PyFreeListState *state)
{

@corona10 corona10 Dec 31, 2023 •
edited
Loading

Uh oh!

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

Copy link
Copy Markdown
Member Author

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.

Following functions will be moved here in the end.

  • _PyTuple_ClearFreeList
  • _PyFloat_ClearFreeList
  • _PyDict_ClearFreeList
  • _PyAsyncGen_ClearFreeLists
  • _PyContext_ClearFreeList

Sorry, something went wrong.

Uh oh!

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

All reactions
@corona10
Update finalize step
7aa956a
corona10
corona10 commented Dec 31, 2023
View reviewed changes
Comment thread Python/pylifecycle.c Outdated
*/

static void
finalize_free_lists(PyFreeListState *state)

@corona10 corona10 Dec 31, 2023

Copy link
Copy Markdown
Member Author

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.

Following functions will be moved here in the end.

  • _PyDict_Fini
  • _PyTuple_Fini
  • _PySlice_Fini
  • _PyFloat_Fini
  • _PyContext_Fini

Sorry, something went wrong.

Uh oh!

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

All reactions
corona10
corona10 commented Dec 31, 2023
View reviewed changes
Comment thread Modules/gcmodule.c Resolved

Uh oh!

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

@corona10
pep7
908ef13
@corona10

corona10 commented Dec 31, 2023

Copy link
Copy Markdown
Member Author

@pablogsal @colesbury
This PR is now ready to be reviewed :)
Please take a look, and happy new free-threaded year!!

All reactions

Sorry, something went wrong.

Uh oh!

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

@corona10
Update
0096383
@corona10 corona10 changed the title gh-111968: Introduce PyFreeListState and _PyFreeListState_GET API [WIP] gh-111968: Introduce PyFreeListState and _PyFreeListState_GET API Jan 2, 2024
@corona10 corona10 changed the title [WIP] gh-111968: Introduce PyFreeListState and _PyFreeListState_GET API [WIP] gh-111968: Introduce _PyFreeListState and _PyFreeListState_GET API Jan 2, 2024
erlend-aasland
erlend-aasland reviewed Jan 5, 2024
View reviewed changes
Comment thread Makefile.pre.in Resolved

Uh oh!

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

corona10 added 2 commits January 6, 2024 09:21
@corona10
fix
2811a12
@corona10
fix compiler warn
a5f494d
@corona10

corona10 commented Jan 6, 2024

Copy link
Copy Markdown
Member Author

@colesbury @pablogsal PTAL

All reactions

Sorry, something went wrong.

Uh oh!

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

corona10 added 3 commits January 6, 2024 09:54
@corona10
nit
837ae60
@corona10
fix
08c8613
@corona10
Adjust comment
b5eb472
@corona10
corona10 force-pushed the gh-111968 branch from 3dc6ee5 to b5eb472 Compare January 6, 2024 04:31
@erlend-aasland
2 tabs, not 8 spaces
0d8dc3d
pablogsal
pablogsal reviewed Jan 8, 2024
View reviewed changes
Comment thread Include/internal/pycore_gc.h Outdated

// Functions to clear types free lists
extern void _PyGC_ClearFreeList(PyInterpreterState *interp);
extern void _Py_ClearFreeLists(_PyFreeListState *state);

@pablogsal pablogsal Jan 8, 2024

Copy link
Copy Markdown
Member

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.

Hummm, I find this asymmetry a bit odd. Wouldn't be better to keep all functions receiving PyInterpreterState *interp and then fetching the freelist state from there instead?

That way the code of the caller will be also cleaner and doesn't need to deal with where the freelist is stored.

Sorry, something went wrong.

Uh oh!

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

All reactions

@colesbury colesbury Jan 8, 2024

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.

In the free-threaded builds, we want to clear the free-lists for a specific thread (not all threads). Passing interp doesn't provide enough information. In some cases the thread we are clearing is not even the active thread, such as when we call PyThreadState_Clear() on dead threads after fork.

Sorry, something went wrong.

Uh oh!

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

pablogsal and corona10 reacted with thumbs up emoji
All reactions
  • 👍 2 reactions
pablogsal
pablogsal reviewed Jan 8, 2024
View reviewed changes
Comment thread Python/gc_free_threading.c
_PyAsyncGen_ClearFreeLists(interp);
_PyContext_ClearFreeList(interp);

HEAD_LOCK(&_PyRuntime);

@pablogsal pablogsal Jan 8, 2024

Copy link
Copy Markdown
Member

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.

This locks interpreters creation, but not thread creation, no? Is it possible that this races with thread creation/destruction? I am missing something?

Sorry, something went wrong.

Uh oh!

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

All reactions

@colesbury colesbury Jan 8, 2024

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.

This part looks okay to me. The HEAD_LOCK() protects the threads linked list (among other things). Threads acquire the HEAD_LOCK() when appending (or removing) themselves to that list.

cpython/Python/pystate.c

Lines 1370 to 1371 in ace4d7f

/* We serialize concurrent creation to protect global state. */
HEAD_LOCK(runtime);

Modification of the free-lists themselves is protected by the "stop-the-world" pause (or the GIL), which is not yet implemented.

Sorry, something went wrong.

Uh oh!

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

pablogsal and corona10 reacted with thumbs up emoji
All reactions
  • 👍 2 reactions
colesbury
colesbury reviewed Jan 8, 2024
View reviewed changes

@colesbury colesbury 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.

This generally looks good to me.

I find the code organization a bit confusing: we have free list handling split across a lot of files. The declarations of some functions are in headers that don't correspond to the files where those functions are defined. For example, _Py_ClearFreeLists() is declared in pycore_gc.h but defined in pystate.c.

I think it'll be worth doing a refactor/reorganization after more functions are converted to this pattern. (I'm not sure it's worth doing now.)

Sorry, something went wrong.

Uh oh!

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

All reactions
Comment thread Python/gc_free_threading.c
_PyAsyncGen_ClearFreeLists(interp);
_PyContext_ClearFreeList(interp);

HEAD_LOCK(&_PyRuntime);

@colesbury colesbury Jan 8, 2024

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.

This part looks okay to me. The HEAD_LOCK() protects the threads linked list (among other things). Threads acquire the HEAD_LOCK() when appending (or removing) themselves to that list.

cpython/Python/pystate.c

Lines 1370 to 1371 in ace4d7f

/* We serialize concurrent creation to protect global state. */
HEAD_LOCK(runtime);

Modification of the free-lists themselves is protected by the "stop-the-world" pause (or the GIL), which is not yet implemented.

Sorry, something went wrong.

Uh oh!

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

pablogsal and corona10 reacted with thumbs up emoji
All reactions
  • 👍 2 reactions
Comment thread Include/internal/pycore_gc.h Resolved

Uh oh!

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

Comment thread Python/pystate.c Outdated
#ifdef Py_GIL_DISABLED
// Each thread should clear own freelists in free-threading builds.
_PyFreeListState *freelist_state = &((_PyThreadStateImpl*)tstate)->freelist_state;
_Py_ClearFreeLists(freelist_state);

@colesbury colesbury Jan 8, 2024

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.

Can we pass something like int is_finalization as an argument to _Py_ClearFreeLists()? I am concerned about the issue that _PyList_Fini() attempts to detect by setting num_free=-1: allocating objects after the free list is cleared for the final time. We want that error detection here.

Something like:

_Py_ClearFreeLists(freelist_state, 1);

and in the code clearing free lists

_PyList_ClearFreeList(_PyFreeListState *freelist_state, int is_finalization)
{
    ....
   if (is_finalization) {
     state->numfree = -1;
   }
}

Along those lines, I think we should move the _Py_ClearFreeLists() call after the on_delete() call since, on_delete() can free some Python objects.

Sorry, something went wrong.

Uh oh!

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

corona10 reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

@corona10 corona10 Jan 9, 2024

Copy link
Copy Markdown
Member Author

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.

@colesbury We may need to change the assertion of

cpython/Objects/listobject.c

Lines 366 to 367 in a023bc2

// list_dealloc() must not be called after _PyList_Fini()
assert(state->numfree != -1);

If we mark it at the PyThreadState_Clear phase.

Sorry, something went wrong.

Uh oh!

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

All reactions
Comment thread Include/internal/pycore_gc.h Outdated

// Functions to clear types free lists
extern void _PyGC_ClearFreeList(PyInterpreterState *interp);
extern void _Py_ClearFreeLists(_PyFreeListState *state);

@colesbury colesbury Jan 8, 2024

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.

In the free-threaded builds, we want to clear the free-lists for a specific thread (not all threads). Passing interp doesn't provide enough information. In some cases the thread we are clearing is not even the active thread, such as when we call PyThreadState_Clear() on dead threads after fork.

Sorry, something went wrong.

Uh oh!

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

pablogsal and corona10 reacted with thumbs up emoji
All reactions
  • 👍 2 reactions
corona10 added 5 commits January 9, 2024 09:18
@corona10
Rename to _PyGC_ClearAllFreeLists
fe859e1
@corona10
Pass is_finalization to _PyList_ClearFreeList
c284061
@corona10
fix
a8e39b3
@corona10
fix
99ac375
@corona10
fix
0c331c7
@corona10 corona10 changed the title gh-111968: Introduce _PyFreeListState and _PyFreeListState_GET API [WIP] gh-111968: Introduce _PyFreeListState and _PyFreeListState_GET API Jan 9, 2024
@corona10 corona10 changed the title [WIP] gh-111968: Introduce _PyFreeListState and _PyFreeListState_GET API gh-111968: Introduce _PyFreeListState and _PyFreeListState_GET API Jan 9, 2024
@corona10

corona10 commented Jan 9, 2024

Copy link
Copy Markdown
Member Author

For example, _Py_ClearFreeLists() is declared in pycore_gc.h but defined in pystate.c.

It's due to the complex of dependency of headers once we move all domains into pycore_freelist.h, we can clean up the location issue. Let's handle it separately :)

All reactions

Sorry, something went wrong.

Uh oh!

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

@corona10
corona10 requested a review from colesbury January 9, 2024 15:21
colesbury
colesbury approved these changes Jan 9, 2024
View reviewed changes
@corona10
corona10 merged commit 57bdc6c into python:main Jan 9, 2024
@bedevere-app bedevere-app Bot removed the awaiting core review label Jan 9, 2024
@corona10
corona10 deleted the gh-111968 branch January 9, 2024 23:04
@corona10 corona10 mentioned this pull request Jan 13, 2024
Clear per-thread free-list concurrently from GC #114016
Open
kulikjak pushed a commit to kulikjak/cpython that referenced this pull request Jan 22, 2024
@corona10 @kulikjak
pythongh-111968: Introduce _PyFreeListState and _PyFreeListState_GET …
a7e3b5f
…API (pythongh-113584)
@corona10 corona10 mentioned this pull request Jan 26, 2024
gh-111968: Use per-thread freelists for dict in free-threading #114323
Merged
aisk pushed a commit to aisk/cpython that referenced this pull request Feb 11, 2024
@corona10 @aisk
pythongh-111968: Introduce _PyFreeListState and _PyFreeListState_GET …
7e32c02
…API (pythongh-113584)
Glyphack pushed a commit to Glyphack/cpython that referenced this pull request Sep 2, 2024
@corona10 @Glyphack
pythongh-111968: Introduce _PyFreeListState and _PyFreeListState_GET …
2cdb9b2
…API (pythongh-113584)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@pablogsal pablogsal pablogsal left review comments
@erlend-aasland erlend-aasland erlend-aasland left review comments
@colesbury colesbury colesbury approved these changes
@DinoV DinoV Awaiting requested review from DinoV

Uh oh!

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

Assignees

No one assigned

Labels

skip news topic-free-threading

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.

4 participants

@corona10 @erlend-aasland @pablogsal @colesbury
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 01402520 — 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.