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-108634: Py_TRACE_REFS uses a hash table by vstinner · Pull Request #108663 · python/cpython

Conversation

@vstinner

@vstinner vstinner commented Aug 30, 2023 •
edited by github-actions Bot
Loading

Uh oh!

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

Copy link
Copy Markdown
Member

Python built with "configure --with-trace-refs" (tracing references) is now ABI compatible with Python release build and debug build. Moreover, it now also supports the Limited API.

Change Py_TRACE_REFS build:

  • Remove _PyObject_EXTRA_INIT macro.
  • The PyObject structure no longer has two extra members (_ob_prev and _ob_next).
  • Use a hash table (_Py_hashtable_t) to trace references (all objects): PyInterpreterState.object_state.refchain.
  • Py_TRACE_REFS build is now ABI compatible with release build and debug build.
  • Limited C API extensions can now be built with Py_TRACE_REFS: xxlimited, xxlimited_35, _testclinic_limited.
  • No longer rename PyModule_Create2() and PyModule_FromDefAndSpec2() functions to PyModule_Create2TraceRefs() and PyModule_FromDefAndSpec2TraceRefs().
  • _Py_PrintReferenceAddresses() is now called before finalize_interp_delete() which deletes the refchain hash table.

Test changes for Py_TRACE_REFS:

  • Add test.support.Py_TRACE_REFS constant.
  • Add test_sys.test_getobjects() to test sys.getobjects() function.
  • test_exceptions skips test_recursion_normalizing_with_no_memory() and test_memory_error_in_PyErr_PrintEx() if Python is built with Py_TRACE_REFS.
  • test_repl skips test_no_memory().
  • test_capi skisp test_set_nomemory().
  • Issue: Py_TRACE_REFS is not compatible with Py_LIMITED_API #108634

📚 Documentation preview 📚: https://cpython-previews--108663.org.readthedocs.build/

Sorry, something went wrong.

Uh oh!

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

All reactions
@vstinner
vstinner requested review from brettcannon, corona10, ericsnowcurrently, erlend-aasland, iritkatriel, ncoghlan, rhettinger and warsaw as code owners August 30, 2023 02:30
@bedevere-bot bedevere-bot mentioned this pull request Aug 30, 2023
Py_TRACE_REFS is not compatible with Py_LIMITED_API #108634
Closed
2 tasks done
@bedevere-bot bedevere-bot added the awaiting core review label Aug 30, 2023
@vstinner

vstinner commented Aug 30, 2023

Copy link
Copy Markdown
Member Author

Py_TRACE_REFS adds _Py_AddToAllObjects() and _Py_ForgetReference() to the private functions. These functions are not called by the public C API (only by the internal C API).

_Py_AddToAllObjects() is called by PyType_Ready() and _Py_NewReference().

_Py_ForgetReference() is called by _Py_Dealloc() and allocator functions using free lists (bytes, tuple, str).

These changes have no impact on the ABI. So the Py_TRACE_REFS is now ABI compatible with release and debug builds.

All reactions

Sorry, something went wrong.

Uh oh!

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

@vstinner vstinner mentioned this pull request Aug 30, 2023
gh-85283: _stat extension uses the limited C API #108573
Closed
@vstinner

vstinner commented Aug 30, 2023

Copy link
Copy Markdown
Member Author

!buildbot TraceRefs

All reactions

Sorry, something went wrong.

Uh oh!

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

@bedevere-bot

bedevere-bot commented Aug 30, 2023

Copy link
Copy Markdown

🤖 New build scheduled with the buildbot fleet by @vstinner for commit b52011d 🤖

The command will test the builders whose names match following regular expression: TraceRefs

The builders matched are:

All reactions

Sorry, something went wrong.

Uh oh!

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

@vstinner

vstinner commented Aug 30, 2023

Copy link
Copy Markdown
Member Author

The builders matched are:

Oh, it seems like "AMD64 Arch Linux TraceRefs 3.x" buildbot https://buildbot.python.org/all/#/builders/484 is not used from this GitHub command, !buildbot TraceRefs.

All reactions

Sorry, something went wrong.

Uh oh!

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

@vstinner

vstinner commented Aug 30, 2023

Copy link
Copy Markdown
Member Author

_PyRefchain_Trace() calls Py_FatalError() which kills the program with abort() (which may write a coredump file, depending on the system configuration). That's not great, but I didn't want to change _Py_NewReference() API to report an error only for Py_TRACE_REFS build, whereas this function cannot fail otherwise.

All reactions

Sorry, something went wrong.

Uh oh!

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

@vstinner

vstinner commented Aug 30, 2023

Copy link
Copy Markdown
Member Author

cc @serhiy-storchaka @pablogsal @erlend-aasland @corona10

All reactions

Sorry, something went wrong.

Uh oh!

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

@vstinner

vstinner commented Aug 30, 2023

Copy link
Copy Markdown
Member Author

Failed builds:

  • buildbot/PPC64LE Fedora Stable Clang Installed PR
  • buildbot/aarch64 Fedora Stable Clang Installed PR

test_zippath_from_non_installed_posix() and test_upgrade_dependencies() of test_venv failed: known issue #103224, unrelated to this PR.

All reactions

Sorry, something went wrong.

Uh oh!

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

@serhiy-storchaka
serhiy-storchaka requested review from pablogsal and serhiy-storchaka and removed request for brettcannon, ericsnowcurrently, iritkatriel, ncoghlan, rhettinger and warsaw August 30, 2023 07:35
@erlend-aasland

erlend-aasland commented Aug 30, 2023

Copy link
Copy Markdown
Contributor

I'm not qualified to review this, but nevertheless, here's my unqualified opinion: the idea of using a hash map instead of patching the object layout seems good to me; making the trace ref build ABI compatible with ordinary build seems like a big win. I'll leave the proper review to someone who knows the GC better (for example, Pablo was already CC'd on this PR).

The configure changes are fine.

All reactions

Sorry, something went wrong.

Uh oh!

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

@serhiy-storchaka
serhiy-storchaka requested review from methane and pitrou August 30, 2023 07:43
methane
methane reviewed Aug 30, 2023
View reviewed changes
Comment thread Objects/object.c Resolved

Uh oh!

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

@vstinner
_Py_AddToAllObjects(): remove force parameter
68e398d
@vstinner
vstinner force-pushed the refchain branch from b52011d to 68e398d Compare August 30, 2023 11:59
@vstinner
vstinner requested a review from markshannon as a code owner August 30, 2023 11:59
@vstinner

vstinner commented Aug 30, 2023

Copy link
Copy Markdown
Member Author

I removed the force parameter and rebased the PR on the main branch.

All reactions

Sorry, something went wrong.

Uh oh!

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

@pitrou

pitrou commented Aug 30, 2023

Copy link
Copy Markdown
Member

How often is Py_TRACE_REFS used? Did you measure the overhead of your new implementation compared to the old one?

All reactions

Sorry, something went wrong.

Uh oh!

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

@vstinner

vstinner commented Aug 30, 2023

Copy link
Copy Markdown
Member Author

For a debug build, I don't really care of the memory usage (if it's "reasonable"). For example, enabling tracemalloc to trace Python memory allocation almost doubles the Python memory usage!

This PR increases the peak memory usage of a Py_TRACE_REFS build by +29%: 11 899 kiB => 15 408 kiB (+3 509 kiB). Test on ./python -m test test_sys peak Python memory usage.

How often is Py_TRACE_REFS used? Did you measure the overhead of your new implementation compared to the old one?

As far as I know, the main user is @pablogsal's TraceRefs buildbot which makes sure that Python still builds successfully with Py_TRACE_REFS (and that the test suite pass, as well).

On Python 3.7 and older, ./configure --with-pydebug defined Py_TRACE_REFS. Since Python 3.8, you now have to opt-in for it: ./configure --with-trace-refs. I expect that nobody uses such build, only a few core devs for specific debug tasks (who? I have no idea).


I expect that the main difference of my change is the memory usage. I measured it with:

$ ./python -X tracemalloc -i -m test test_sys
(...)
>>> import tracemalloc; print("peak Python memory usage: %.0f kiB" % (tracemalloc.get_traced_memory()[1] / 1024))

Python built with: ./configure --with-pydebug --with-trace-refs && make. It uses gcc -Og.

Memoy usage of Py_REF_DEBUG + Py_TRACE_REFS:

  • main branch: peak Python memory usage: 11 899 kiB
  • PR: peak Python memory usage: 15 408 kiB (+3 509 kiB, +29%)

I ran the command 3 times, the first run has a higher peak memory usage, maybe because the first one used more memory to build PYC files.

By the way, len(sys.getobjects(0)) lists 72 289 objects on this test.


For comparison, memory usage of Py_REF_DEBUG (without Py_TRACE_REFS):

  • ./configure --with-pydebug && make (which also uses gcc -Og)
  • main: peak Python memory usage: 10 727 kiB

On the main branch, Py_TRACE_REFS adds 1 172 kiB (+11%).

All reactions

Sorry, something went wrong.

Uh oh!

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

@pitrou

pitrou commented Aug 30, 2023

Copy link
Copy Markdown
Member

Well, why do we care about improving Py_TRACE_REFS if we think nobody uses it? :-)

All reactions

Sorry, something went wrong.

Uh oh!

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

@vstinner

vstinner commented Aug 30, 2023 •
edited
Loading

Uh oh!

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

Copy link
Copy Markdown
Member Author

Well, why do we care about improving Py_TRACE_REFS if we think nobody uses it? :-)

I would like to convert some stdlib C extensions to the limited C API:

  • https://discuss.python.org/t/use-the-limited-c-api-for-some-of-our-stdlib-c-extensions/32465
  • [C API] Convert a few stdlib extensions to the limited C API (PEP 384) #85283

The practical problem is that we do have a TraceRefs buildbot, and I care of having only green buildbots.

Also, since it's unclear to me who uses TraceRefs, I prefer to fix it rather than ask who use it, or propose to deprecate/remove the feature. In the past, I removed COUNT_ALLOCS build, but this one was used by no one, and there was no buildbot :-)

Right now, trying to workaround TraceRefs build error with Py_LIMITED_API causes me headaches... I wrote a trivial PR to convert the _stat extension to the limited C API: PR #108573. But it breaks the Py_TRACE_REFS build, and so will break the TraceRefs buildbot. I tried to skip the _stat extension if Py_TRACE_REFS, it's optional, but then I got new issues: issue #108638...

In short, fixing Py_LIMITED_API support for Py_TRACE_REFS looks simpler to me than trying to workaround Py_TRACE_REFS build errors :-)

Also, well, IMO it's nice to have the same ABI for all Python builds! It should make these builds usable in more cases. I always wanted to give a try to the hash table idea. As you can see, it's not that complicated.

All reactions

Sorry, something went wrong.

Uh oh!

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

@vstinner

vstinner commented Aug 30, 2023

Copy link
Copy Markdown
Member Author

On my _stat PR, @AA-Turner seems to be worried of breaking TraceRefs buildbot: #108573 (comment)

All reactions

Sorry, something went wrong.

Uh oh!

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

@erlend-aasland

This comment was marked as off-topic.

Sign in to view
@pitrou

pitrou commented Aug 30, 2023

Copy link
Copy Markdown
Member

Hmm, I don't think I have ever used Py_TRACE_REFS for CPython core development.

All reactions

Sorry, something went wrong.

Uh oh!

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

@vstinner

vstinner commented Aug 30, 2023

Copy link
Copy Markdown
Member Author

how are you going to hunt ref leaks if you cannot use Py_TRACE_REFS?

I don't use Py_TRACE_REFS for that: https://vstinner.github.io/debug-python-refleak.html

I'm not sure what are the use cases of Py_TRACE_REFS and the sys.getobjects() function.

All reactions

Sorry, something went wrong.

Uh oh!

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

@erlend-aasland

This comment was marked as off-topic.

Sign in to view
@vstinner

vstinner commented Aug 30, 2023

Copy link
Copy Markdown
Member Author

Well, @methane and @pitrou, tell me if you plan to review this change :-)

All reactions

Sorry, something went wrong.

Uh oh!

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

methane
methane approved these changes Aug 31, 2023
View reviewed changes
@bedevere-bot bedevere-bot added awaiting merge and removed awaiting core review labels Aug 31, 2023
@vstinner

vstinner commented Aug 31, 2023 •
edited
Loading

Uh oh!

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

Copy link
Copy Markdown
Member Author

I checked that this change does not introduce new memory leak:

vstinner@mona$ PYTHONMALLOC=malloc valgrind ./python -c pass
==2715186== Memcheck, a memory error detector
==2715186== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==2715186== Using Valgrind-3.21.0 and LibVEX; rerun with -h for copyright info
==2715186== Command: ./python -c pass
==2715186== 
==2715186== 
==2715186== HEAP SUMMARY:
==2715186==     in use at exit: 0 bytes in 0 blocks
==2715186==   total heap usage: 52,597 allocs, 52,597 frees, 5,260,667 bytes allocated
==2715186== 
==2715186== All heap blocks were freed -- no leaks are possible
==2715186== 
==2715186== For lists of detected and suppressed errors, rerun with: -s
==2715186== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

There is no leak. For comparison, if I comment _PyObject_FiniState() in PyInterpreterState_Delete(), leak on purpose for the test:

...
==2715502== LEAK SUMMARY:
==2715502==    definitely lost: 0 bytes in 0 blocks
==2715502==    indirectly lost: 0 bytes in 0 blocks
==2715502==      possibly lost: 0 bytes in 0 blocks
==2715502==    still reachable: 14,448 bytes in 195 blocks
==2715502==         suppressed: 0 bytes in 0 blocks
==2715502== Rerun with --leak-check=full to see details of leaked memory
...
All reactions

Sorry, something went wrong.

Uh oh!

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

@vstinner
vstinner merged commit 13a0007 into python:main Aug 31, 2023
@vstinner
vstinner deleted the refchain branch August 31, 2023 16:33
@bedevere-bot bedevere-bot removed the awaiting merge label Aug 31, 2023
@vstinner

vstinner commented Aug 31, 2023

Copy link
Copy Markdown
Member Author

Thanks for the review @methane and @pitrou! I merged my PR which adds more tests and enhance some documentation.

All reactions

Sorry, something went wrong.

Uh oh!

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

@vstinner vstinner mentioned this pull request Sep 4, 2023
Issues with the Stable ABI capi-workgroup/problems#4
Closed
andersk added a commit to andersk/cpython that referenced this pull request Sep 7, 2023
@andersk
Remove remaining LIMITED_API_AVAILABLE checks
c7724e0
Commit 13a0007 (python#108663) made all
Python builds compatible with the Limited API, and removed the
LIMITED_API_AVAILABLE flag.  However, some tests were still checking
for that flag, so they were now being incorrectly skipped.  Remove
these checks to let these tests run again.

Signed-off-by: Anders Kaseorg <[email protected]>
@andersk andersk mentioned this pull request Sep 7, 2023
Limited API tests are now incorrectly skipped unconditionally #109045
Closed
andersk added a commit to andersk/cpython that referenced this pull request Sep 7, 2023
@andersk
pythongh-109045: Remove remaining LIMITED_API_AVAILABLE checks in tests
5c0de5e
Commit 13a0007 (python#108663) made all
Python builds compatible with the Limited API, and removed the
LIMITED_API_AVAILABLE flag.  However, some tests were still checking
for that flag, so they were now being incorrectly skipped.  Remove
these checks to let these tests run again.

Signed-off-by: Anders Kaseorg <[email protected]>
@andersk andersk mentioned this pull request Sep 7, 2023
gh-109045: Remove remaining LIMITED_API_AVAILABLE checks in tests #109046
Merged
andersk
andersk reviewed Sep 7, 2023
View reviewed changes
Comment thread Modules/_testcapi/parts.h
#ifdef Py_TRACE_REFS
#undef LIMITED_API_AVAILABLE
#else
#define LIMITED_API_AVAILABLE 1

@andersk andersk Sep 7, 2023

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 flag is still referenced in Modules/_testcapi/heaptype_relative.c, Modules/_testcapi/vectorcall_limited.c, Modules/_testcapimodule.c, which means the limited API tests are now being incorrectly skipped unconditionally.

  • Limited API tests are now incorrectly skipped unconditionally #109045

Sorry, something went wrong.

Uh oh!

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

All reactions
vstinner pushed a commit that referenced this pull request Sep 7, 2023
@andersk
gh-109045: Remove remaining LIMITED_API_AVAILABLE checks in tests (#1…
f42edf1
…09046)

Commit 13a0007 (#108663) made all
Python builds compatible with the Limited API, and removed the
LIMITED_API_AVAILABLE flag.  However, some tests were still checking
for that flag, so they were now being incorrectly skipped.  Remove
these checks to let these tests run again.

Signed-off-by: Anders Kaseorg <[email protected]>
@ngoldbaum ngoldbaum mentioned this pull request Jan 15, 2026
Remove Py_TRACE_REFS wrappers PyO3/pyo3#5736
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
@erlend-aasland erlend-aasland Awaiting requested review from erlend-aasland erlend-aasland is a code owner
@corona10 corona10 Awaiting requested review from corona10 corona10 is a code owner
@serhiy-storchaka serhiy-storchaka Awaiting requested review from serhiy-storchaka
@pablogsal pablogsal Awaiting requested review from pablogsal
@pitrou pitrou Awaiting requested review from pitrou
@markshannon markshannon Awaiting requested review from markshannon markshannon is a code owner
+1 more reviewer
@andersk andersk andersk left review comments
Reviewers whose approvals may not affect merge requirements

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.

6 participants

@vstinner @bedevere-bot @erlend-aasland @pitrou @andersk @methane
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.