Skip to content

Allocation tracker: fix the live heap tracking#453

Merged
r1viollet merged 15 commits into
mainfrom
r1viollet/fix_dealloc_events
Oct 22, 2025
Merged

Allocation tracker: fix the live heap tracking#453
r1viollet merged 15 commits into
mainfrom
r1viollet/fix_dealloc_events

Conversation

@r1viollet

@r1viollet r1viollet commented Oct 21, 2025

Copy link
Copy Markdown
Collaborator

What does this PR do?

Replace the bitset data structure with something that will not suffer from collisions.
Please refer to the allocation_tracker.md file for up to date notes.

Motivation

Ensure that allocation tracking is correct.

Additional Notes

NA

How to test the change?

There are benchmarks in this PR. They are mostly generated through AI. I do have some doubts on some of the results.
I did some manual testing to check that overhead seems reasonable.
Next step is end to end testing on real workloads.

@r1viollet
r1viollet requested a review from nsavoire as a code owner October 21, 2025 14:27
@pr-commenter

pr-commenter Bot commented Oct 21, 2025

Copy link
Copy Markdown

Benchmark results for collatz

Parameters

Baseline Candidate
config baseline candidate
profiler-version ddprof 0.20.0+e7d474bb.79617775 ddprof 0.20.0+f67c50e1.79973302

Summary

Found 0 performance improvements and 0 performance regressions! Performance is the same for 1 metrics, 0 unstable metrics.

See unchanged results
scenario Δ mean execution_time
scenario:ddprof -S bench-collatz --preset cpu_only collatz_runner.sh same

@pr-commenter

pr-commenter Bot commented Oct 21, 2025

Copy link
Copy Markdown

Benchmark results for BadBoggleSolver_run

Parameters

Baseline Candidate
config baseline candidate
profiler-version ddprof 0.20.0+e7d474bb.79617775 ddprof 0.20.0+f67c50e1.79973302

Summary

Found 0 performance improvements and 0 performance regressions! Performance is the same for 1 metrics, 0 unstable metrics.

See unchanged results
scenario Δ mean execution_time
scenario:ddprof -S bench-bad-boggle-solver BadBoggleSolver_run work 1000 unsure
[-14.501ms; -2.665ms] or [-0.734%; -0.135%]

@r1viollet
r1viollet force-pushed the r1viollet/fix_dealloc_events branch from b2b2c94 to 623cd99 Compare October 21, 2025 15:18
Comment thread benchmark_overhead.sh Outdated

@KowalskiThomas KowalskiThomas left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Haven't reviewed tests yet, will do later!

Comment thread docs/allocation_tracker.md Outdated
Comment thread docs/allocation_tracker.md
Comment thread include/lib/address_bitset.hpp
Comment thread include/lib/address_bitset.hpp Outdated
Comment thread include/lib/address_sampler.hpp Outdated
Comment thread src/lib/address_bitset.cc Outdated
Comment thread src/lib/address_bitset.cc Outdated
Comment thread src/lib/address_bitset.cc Outdated
Comment on lines +136 to +137
// Linear probing to find an empty/deleted slot or the address
for (unsigned probe = 0; probe < AddressTable::kMaxProbeDistance; ++probe) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I remember yesterday Cursor said it would be smart to do quadratic probing and you seemed to agree, did you eventually decide against it?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes, this was a pretty good suggestion. I will get back to testing this. Though I did want to secure a first fix.

Comment thread src/lib/address_bitset.cc
Comment on lines +154 to +157
// Check if slot already contains our address
if (current == addr) {
return false; // Already tracked
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If I understand correctly, we get here if either the current value is not empty/deleted or if CAS failed (and we reloaded the "actual" current value into current after the failed CAS).

What I don't understand is in what case current == addr may be true. From what I gather, it would mean either (1) the memory was previously added into the table before we even tried to insert it (but I don't understand when this would happen) (2) another thread tried to insert the same address we wanted to insert into the table at the same time as we did (but again, I would expect malloc to return each address only to one caller, so I don't understand when this would happen)

I'm definitely not saying this is wrong, I'm just curious to understand why we need it 😅

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I can kind of see a world where we mess up instrumenting a free, so malloc already freed this (but did not remove), then we try to re-add it on subsequent alloc.
I do not really see this as expected though.
So your point might be that we should be watching these more carefully, which is correct.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Makes sense to me, it probably doesn't hurt (much) to account for this case anyway! Thanks for the explanation.

Comment thread src/lib/address_bitset.cc
Comment thread include/lib/address_sampler.hpp Outdated
// Check if we reached max number of elements
// Clear elements if we reach too many
// todo: should we just stop new live tracking (like java) ?
if (IsDDResOK(push_clear_live_allocation(tl_state))) {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

We would need to work on the clear strategy.
For now I have to remove this.

@r1viollet

Copy link
Copy Markdown
Collaborator Author
  • Is this acceptable with prod workloads ?

The fixed sizes might be too small. I expect some tables will be created with almost nothing, whereas other tables will quickly be filled.
Example: could we have a separate tracking for mappings ? I could use a hint on the code path we are using (example: mmap & munmap get a single table).

- Introduce a table for large allocations
- Avoid creating tables on the free code path
@r1viollet

r1viollet commented Oct 22, 2025

Copy link
Copy Markdown
Collaborator Author
  • Is this acceptable with prod workloads ?

The fixed sizes might be too small. I expect some tables will be created with almost nothing, whereas other tables will quickly be filled. Example: could we have a separate tracking for mappings ? I could use a hint on the code path we are using (example: mmap & munmap get a single table).

I added a separate hashmap for mmap allocations.
Looking forwards to dogfooding this to figure out if it works well!

Comment thread include/lib/address_bitset.hpp Outdated
- cleanup notes with more accurate numbers on overhead.
- cleanup duplicate variable

@KowalskiThomas KowalskiThomas left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What I'm seeing makes sense to me with my limited knowledge of ddprof

Approving (but maybe take it with a grain of salt) 🙈

Comment thread src/lib/address_bitset.cc
Comment on lines +154 to +157
// Check if slot already contains our address
if (current == addr) {
return false; // Already tracked
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Makes sense to me, it probably doesn't hurt (much) to account for this case anyway! Thanks for the explanation.

@r1viollet
r1viollet merged commit 5031ff7 into main Oct 22, 2025
2 checks passed
@r1viollet
r1viollet deleted the r1viollet/fix_dealloc_events branch October 22, 2025 15:26
@r1viollet

Copy link
Copy Markdown
Collaborator Author

@nsavoire fyi, when you have some spare time to review 🙇

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.

2 participants