andygrove opened a new pull request, #5991:
URL: https://github.com/apache/datafusion-comet/pull/5991

   ## Which issue does this PR close?
   
   Closes #5990.
   
   ## Rationale for this change
   
   `analyze_trace` compares the process-wide allocation counter against the 
total memory reserved by Comet's pools, and reports points where allocation 
exceeds it. It derives that total by summing the per-thread 
`thread_NNN_comet_memory_reserved` counters:
   
   ```rust
   let pool_total: u64 = pool_by_thread.values().sum();
   ```
   
   That is not the total reserved. Those counters come from 
`total_reserved_for_thread`, which sums the pools registered on one thread and 
deduplicates shared pools only *within* that thread. Task-shared pools are 
shared *across* threads, so every thread referencing one reports its full 
reservation, and summing across threads multiplies it by the number of 
referencing threads.
   
   Measured on TPC-H SF100 (2 executors x 8 cores, Spark 4.1.1, 16g off-heap, 
tracing enabled): the reported total reached **500x** the real allocation, 
**27%** of samples claimed more memory reserved than the allocator had handed 
out, and the median reported total was **0** because threads with no registered 
pools contribute nothing. The tool's "peak gap" then landed on samples where 
the total happened to be zero, so it reported peak allocation rather than a gap.
   
   The tool is documented in the contributor guide and is used to investigate 
exactly the memory accounting questions tracked in #4576, so wrong numbers here 
are actively misleading. Correcting the source changed the same traces 
substantially: peak gap fell from 1694 MB to 560 MB.
   
   ## What changes are included in this PR?
   
   - `total_reserved_across_tasks()` in 
`native/core/src/execution/memory_pools/task_shared.rs` sums `reserved()` over 
the distinct entries of `TASK_SHARED_MEMORY_POOLS`. The registry is keyed by 
task attempt, so each pool is counted exactly once regardless of how many 
threads reference it.
   - `jni_api.rs` emits that as a single `comet_memory_reserved_total` counter, 
at the same point `native_allocated` is already emitted, so both halves of a 
sample are true at the same instant. The per-thread counters are unchanged, 
since they remain useful for per-thread attribution in a trace viewer.
   - `analyze_trace.rs` prefers `comet_memory_reserved_total` when the trace 
carries it. Traces without it still analyze, using the per-thread sum, but the 
tool now says plainly that those numbers over-count.
   
   Two details worth flagging for review:
   
   - The total must be matched before the existing 
`name.contains("comet_memory_reserved")` branch, which would otherwise also 
match `comet_memory_reserved_total` and fold the process-wide counter into the 
per-thread map.
   - Anchoring matters independently of the sum. The counters are emitted in 
the order allocated, per-thread, total, so pairing a sample on the allocation 
counter alone picks up the previous group's total. That lag alone accounted for 
part of the difference between a 1694 MB and a 560 MB peak gap when this was 
measured offline.
   
   ## How are these changes tested?
   
   - Two new unit tests for `total_reserved_across_tasks()`. The first covers 
the case this bug is about: a task-shared pool referenced by several execution 
contexts is counted once, not once per reference. The second covers release, 
that dropping the last reference removes the pool from the total. Both take a 
serial lock, because the registry is process-wide and the crate's tests run in 
parallel, so without it the two tests observe each other's reservations. #5212 
notes there are currently no unit tests for any of the pools.
   - Verified end to end by running the built `analyze_trace` against a real 
TPC-H SF100 trace, once as recorded and once with the new counter stripped out 
to exercise the fallback. Same trace, same allocation counter:
   
     | pool total source | peak pool total |
     | --- | --- |
     | `comet_memory_reserved_total` | 2080.3 MB |
     | sum of 8 per-thread counters | 2896.2 MB |
   
     Peak `native_allocated` on that trace was 2100.3 MB, so the per-thread sum 
invents about 816 MB of reservation that was never held. The fallback path 
prints the over-count warning and still produces a report, so existing traces 
remain readable.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to