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 — bpo-40521: Make dict free lists per-interpreter by vstinner · Pull Request #20645 · python/cpython

Conversation

@vstinner

@vstinner vstinner commented Jun 5, 2020 •
edited by bedevere-bot
Loading

Uh oh!

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

Copy link
Copy Markdown
Member

Each interpreter now has its own dict free list:

  • Move dict free lists into PyInterpreterState.
  • Move PyDict_MAXFREELIST define to pycore_interp.h
  • Add _Py_dict_state structure.
  • Add tstate parameter to _PyDict_ClearFreeList() and _PyDict_Fini().
  • _PyLong_Fini() and _PyFloat_Fini() are now called after
    _PyDict_Fini().
  • Remove "#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS".

https://bugs.python.org/issue40521

Sorry, something went wrong.

Uh oh!

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

All reactions
@vstinner
vstinner requested review from methane and pablogsal as code owners June 5, 2020 01:02
@the-knights-who-say-ni the-knights-who-say-ni added the CLA signed label Jun 5, 2020
@bedevere-bot bedevere-bot added the awaiting core review label Jun 5, 2020
@vstinner

vstinner commented Jun 5, 2020 •
edited by bedevere-bot
Loading

Uh oh!

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

Copy link
Copy Markdown
Member Author

After tuple (commit 69ac6e5) and list (commit 88ec919) and others types (see bpo-40521), it's now the turn of dict to get its free lists moved to PyInterpreterState! FYI when I measured the tuple PR overhead, it was around 1 ns (and create a tuple of 1 item is around 20 ns): see PR #20247.

cc @methane @pablogsal

All reactions

Sorry, something went wrong.

Uh oh!

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

@vstinner

vstinner commented Jun 5, 2020

Copy link
Copy Markdown
Member Author

With this PR, all free lists cleared by gc.collect() are per-interpreter.

All reactions

Sorry, something went wrong.

Uh oh!

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

@vstinner

vstinner commented Jun 5, 2020 •
edited
Loading

Uh oh!

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

Copy link
Copy Markdown
Member Author

Before anyone asks, here is a microbenchmark on PyDict_New() to measure the overhead of this PR:

Mean +- std dev: [ref] 10.9 ns +- 0.9 ns -> [patch] 12.8 ns +- 1.0 ns: 1.18x slower (+18%)

The PR adds +1.9 ns per PyDict_New() call.

I used bench_dict.patch which is attached to https://bugs.python.org/issue40521.

UPDATE: please notice that the std dev is around 1 ns which is close to the overhead. These microbenchmark are so small that it is really hard to get a precise measure of timings.

All reactions

Sorry, something went wrong.

Uh oh!

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

@methane

methane commented Jun 5, 2020

Copy link
Copy Markdown
Member

@vstinner Would you benchmark without freelist too?
If benefit of the freelist becomes too small, removing it is better than making it per-interpreter.

All reactions

Sorry, something went wrong.

Uh oh!

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

@vstinner

vstinner commented Jun 5, 2020

Copy link
Copy Markdown
Member Author

@vstinner Would you benchmark without freelist too?

Here you have:

vstinner@apu$ python3 -m pyperf compare_to ref.json patch.json no_freelist.json 
Mean +- std dev: [ref] 10.9 ns +- 0.9 ns -> [patch] 12.8 ns +- 1.0 ns: 1.18x slower (+18%)
Mean +- std dev: [ref] 10.9 ns +- 0.9 ns -> [no_freelist] 18.0 ns +- 1.0 ns: 1.65x slower (+65%)

If benefit of the freelist becomes too small, removing it is better than making it per-interpreter.

Disabling the free list adds +7.1 ns per PyDict_New() call: 1.65x slower. It doesn't sound reasonable to remove free_list in dictobject.c.

All reactions

Sorry, something went wrong.

Uh oh!

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

@vstinner

vstinner commented Jun 8, 2020

Copy link
Copy Markdown
Member Author

TODO: implement commit bcb1983 for dict free lists. See https://bugs.python.org/issue40887 for the context.

All reactions

Sorry, something went wrong.

Uh oh!

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

@vstinner
bpo-40521: Make dict free lists per-interpreter
df1c134
Each interpreter now has its own dict free list:

* Move dict free lists into PyInterpreterState.
* Move PyDict_MAXFREELIST define to pycore_interp.h
* Add _Py_dict_state structure.
* Add tstate parameter to _PyDict_ClearFreeList() and _PyDict_Fini().
* In debug mode, ensure that the dict free lists are not used after
  _PyDict_Fini() is called.
* Remove "#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS".
@vstinner

vstinner commented Jun 22, 2020

Copy link
Copy Markdown
Member Author

@methane: So, what do you think?

I rebased my PR on top of the master branch.

TODO: implement commit bcb1983 for dict free lists. See https://bugs.python.org/issue40887 for the context.

Done. In debug mode, trying to use dict free lists after they are finalized now fails with an assertion error.

All reactions

Sorry, something went wrong.

Uh oh!

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

methane
methane approved these changes Jun 23, 2020
View reviewed changes

@methane methane left a comment

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.

The discussion in the ML didn't go anywhere.
I'm OK to merge this.

Sorry, something went wrong.

Uh oh!

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

All reactions
@bedevere-bot bedevere-bot added awaiting merge and removed awaiting core review labels Jun 23, 2020
@vstinner
vstinner merged commit b4e85ca into python:master Jun 23, 2020
@bedevere-bot bedevere-bot removed the awaiting merge label Jun 23, 2020
@vstinner
vstinner deleted the dict_free_list branch June 23, 2020 09:33
@vstinner

vstinner commented Jun 23, 2020

Copy link
Copy Markdown
Member Author

I'm OK to merge this.

Thanks @methane for the review! I'm still interested to attempt to reduce the overhead of this change. See my PR #20767 for example. But so I failed to find a method which has a significant impact on performance.

Again, measuring performance of a function taking around 10 ns is really hard. The machine code changes depending on LTO and/or PGO build modes, compiler flags, etc. And sometimes it's faster, sometimes it's slower...

All reactions

Sorry, something went wrong.

Uh oh!

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

fasih pushed a commit to fasih/cpython that referenced this pull request Jun 29, 2020
@vstinner @fasihahmad
bpo-40521: Make dict free lists per-interpreter (pythonGH-20645)
f58ee94
Each interpreter now has its own dict free list:

* Move dict free lists into PyInterpreterState.
* Move PyDict_MAXFREELIST define to pycore_interp.h
* Add _Py_dict_state structure.
* Add tstate parameter to _PyDict_ClearFreeList() and _PyDict_Fini().
* In debug mode, ensure that the dict free lists are not used after
  _PyDict_Fini() is called.
* Remove "#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS".
@vstinner vstinner mentioned this pull request Apr 10, 2022
[subinterpreters] Make free lists and unicode caches per-interpreter #84701
Closed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@methane methane methane approved these changes
@pablogsal pablogsal Awaiting requested review from pablogsal

Uh oh!

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

Assignees

No one assigned

Labels

None yet

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

@vstinner @methane @the-knights-who-say-ni @bedevere-bot
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.