Skip to content

Conversation

pablogsal
Copy link
Member

This feature adds the capability to track Python objects throughout
their lifecycle in memray. The implementation introduces a reference
tracking system that records PyObject creation and destruction events,
storing them as TrackedObject records in the memray capture file with
associated stack traces. The Tracker class now accepts a
reference_tracking flag to enable this functionality and provides a
get_surviving_objects() method to retrieve live objects at the end of
tracking.

Object tracking works across threads and supports native, Python, and
hybrid stack traces, providing insights into Python object
lifetimes. This enhancement extends memray beyond memory allocation
tracking to give developers a powerful tool for understanding object
lifecycles and identifying potential reference leaks.

With this addition, memray can now correlate memory allocations with the
Python objects that trigger them, enabling more precise debugging of
memory usage patterns. The feature is particularly useful for
identifying objects that persist longer than expected or detecting
unexpected object creation patterns. By tracking both memory allocations
and object references, memray provides a more complete picture of a
program's memory behavior, helping developers optimize memory usage and
resolve leaks more effectively.

This implementation leverages the new Python reference tracing API that
was introduced in CPython 3.13.

Signed-off-by: Pablo Galindo [email protected]

Issue number of the reported bug or feature request: #

Describe your changes
A clear and concise description of the changes you have made.

Testing performed
Describe the testing you have performed to ensure that the bug has been addressed, or that the new feature works as planned.

Additional context
Add any other context about your contribution here.

@pablogsal pablogsal force-pushed the pyrefs2 branch 7 times, most recently from 32d2317 to d748e4d Compare April 14, 2025 09:10
@codecov-commenter
Copy link

codecov-commenter commented Apr 14, 2025

Codecov Report

❌ Patch coverage is 22.99465% with 288 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.66%. Comparing base (26b7f3b) to head (6d978e1).

Files with missing lines Patch % Lines
tests/integration/test_object_tracking.py 29.44% 139 Missing ⚠️
src/memray/_memray/record_reader.cpp 10.71% 50 Missing ⚠️
src/memray/_memray/tracking_api.cpp 27.27% 40 Missing ⚠️
src/memray/_memray/records.cpp 0.00% 22 Missing ⚠️
src/memray/_memray/record_writer.cpp 23.80% 16 Missing ⚠️
src/memray/_memray/tracking_api.h 0.00% 14 Missing ⚠️
src/memray/_memray/hooks.cpp 0.00% 3 Missing ⚠️
src/memray/_memray/socket_reader_thread.cpp 25.00% 3 Missing ⚠️
src/memray/_memray/records.h 50.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #752      +/-   ##
==========================================
- Coverage   92.01%   90.66%   -1.36%     
==========================================
  Files          95       98       +3     
  Lines       11940    12383     +443     
  Branches      413      420       +7     
==========================================
+ Hits        10987    11227     +240     
- Misses        953     1156     +203     
Flag Coverage Δ
cpp 90.66% <22.99%> (-1.36%) ⬇️
python_and_cython 90.66% <22.99%> (-1.36%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@pablogsal
Copy link
Member Author

Tests require 3.13.3 at least because before there is a bug that causes some objects to be identified wrongly. cibuildwheel only has this when pypa/cibuildwheel#2359 passes

@pablogsal pablogsal force-pushed the pyrefs2 branch 5 times, most recently from 6b081eb to a03e9de Compare April 14, 2025 13:10
@joerick
Copy link

joerick commented Apr 26, 2025

I just released cibuildwheel with 3.13.3 support!

@pablogsal pablogsal marked this pull request as ready for review August 19, 2025 16:01
@godlygeek godlygeek force-pushed the pyrefs2 branch 2 times, most recently from 227cf37 to 9de0d3b Compare August 19, 2025 20:50
Copy link
Contributor

@godlygeek godlygeek left a comment

Choose a reason for hiding this comment

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

Lots of comments, mostly pretty small things. The overall approach looks good to me. I have some concerns about some of the names, and how we handle the uninstallation of the hooks (and maybe even the installation?) in the free-threading world.


# THEN
# No surviving objects should be recorded when reference_tracking is disabled
assert len(tracker.get_surviving_objects()) == 0
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should probably raise an exception if this is called when reference tracking was never enabled. It seems like user error...

Also, this test doesn't prove what it says it does. It would pass even if reference tracking were enabled, because no objects leak (thanks to the del and gc.collect() calls)

This feature adds the capability to track Python objects throughout
their lifecycle in memray. The implementation introduces a reference
tracking system that records PyObject creation and destruction events,
storing them as TrackedObject records in the memray capture file with
associated stack traces. The Tracker class now accepts a
reference_tracking flag to enable this functionality and provides a
get_surviving_objects() method to retrieve live objects at the end of
tracking.

Object tracking works across threads and supports native, Python, and
hybrid stack traces, providing insights into Python object
lifetimes. This enhancement extends memray beyond memory allocation
tracking to give developers a powerful tool for understanding object
lifecycles and identifying potential reference leaks.

With this addition, memray can now correlate memory allocations with the
Python objects that trigger them, enabling more precise debugging of
memory usage patterns. The feature is particularly useful for
identifying objects that persist longer than expected or detecting
unexpected object creation patterns. By tracking both memory allocations
and object references, memray provides a more complete picture of a
program's memory behavior, helping developers optimize memory usage and
resolve leaks more effectively.

This implementation leverages the new Python reference tracing API that
was introduced in CPython 3.13.

Signed-off-by: Pablo Galindo <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants