Conversation
…ry usage Build the alloc-accounting allocator wrapper by default (jemalloc stays opt-in) and have each executor periodically log its native memory usage while Comet native plans run: Comet native memory usage: allocated 5412.3 MiB, reserved 3890.0 MiB (16 native plans, 8 memory pools) The first CometExecIterator on an executor starts one daemon thread that logs a single line per interval for the whole executor, plus one more after the last plan finishes. It samples on a timer rather than between batches because a plan rooted at a native shuffle writer, or fed by native scans, can spend its whole run inside one executePlan call. The interval is spark.comet.memory.logInterval (default 10s, 0 disables), read from the executor's SparkConf. The new Native.getMemoryUsage JNI call reads only the allocation counter and the pool registry, and reads pool reservations after releasing the registry lock: CometFairMemoryPool holds its own lock across the JNI acquire from Spark, which can wait for a finishing task whose releasePlan needs the registry lock. Also add a tuning guide section on using the log to size spark.executor.memoryOverhead, update the tracing and memory management guides, and switch the rust-test CI step to cover the jemalloc arm and the build without the feature.
…gistry lock Remove the alloc-accounting cargo feature: the accounting allocator now wraps whichever backend the build selects, unconditionally. The alloc_overhead bench measures the wrapper against the bare backend in one binary, since there is no longer a build without it. releasePlan read the remaining pools' reservations while holding the pool registry lock on every plan, not only when tracing. With fair_unified that can deadlock: the pool holds its lock across a Spark acquire that waits on another task, whose releasePlan needs the registry lock. Every reader now copies the pools out and reads them after releasing it, and releasePlan reads nothing unless tracing. A malformed spark.comet.memory.logInterval now disables the log with a warning instead of failing every Comet task, and a value set only in the session is reported as ignored. The log also warns when the executor's native footprint (untracked native memory plus Spark's off-heap memory in use) exceeds spark.memory.offHeap.size plus the memory overhead.
The fraction does not reserve room in Spark's off-heap pool: greedy_unified ignores it, and fair_unified applies it per task, where Spark's own per-task limit is tighter. Point the warning and the tuning guide at the memory overhead instead.
The fraction was documented as holding back part of the off-heap pool for native memory that Comet does not reserve, but it cannot: greedy_unified ignores it, fair_unified applies it per task where Spark's own per-task limit is tighter whenever more than one task runs, and Spark hands out the whole pool either way. The only room Spark leaves for untracked native memory is spark.executor.memoryOverhead. Mark the setting deprecated, keep its current behaviour, have the driver plugin warn when it is set, and correct the tuning and memory management guides.
sunchao
approved these changes
Sep 23, 2026
sunchao
left a comment
Member
There was a problem hiding this comment.
Summary
Reviewed the full 19-file, four-commit PR diff against main at 97d1c5e4c3d55b3ae6f8c489b37fc717e434b2ed, including the three commits shared with #6162. No reproducible introduced or materially worsened P1/P2 finding was established. Source review is complete. Full integration and workload-performance validation remain incomplete.
- Prior state and problem: Native allocation accounting was opt-in and required tracing to observe. Pool reservations alone do not describe all native allocations, and registry readers held the registry lock while reading pool reservations. The tuning guidance also presented
spark.comet.exec.memoryPool.fractionas an executor-wide headroom control, although its behavior depends on the pool type and cannot guarantee that headroom across all consumers. - Design approach: The selected Rust allocator is always wrapped for accounting. A JNI snapshot reports allocations, distinct-pool reservations, pool count, and plan count. One executor daemon logs these figures and evaluates an advisory memory threshold. The final commit documents the fraction as deprecated and adds a driver warning when it is explicitly present in
SparkConf. - Correctness / compatibility analysis: The snapshot uses process-wide state and clones pool references under the registry lock, then reads reservations after releasing it. The JNI entry point uses the existing exception/panic boundary. The fraction's default, parsing, budget arithmetic, and reservation behavior remain unchanged. The warning reads its configured value without parsing or mutating it. The cumulative change does not alter expression support levels or Spark memory-acquisition rules. The five isolated allocator tests passed in the shared-commit review, and the tested module is byte-identical at this head. Suite registration and
git diff --checkpassed for this PR. Full native/JVM integration and workload benchmarks were not run locally. The Linux native build and Rust tests were running at the last check. Completed visible checks passed, while macOS, Spark SQL, Iceberg, and benchmark jobs were skipped. - Key design decisions: Accounting applies to every allocator backend even when logging is disabled. Logging reads executor configuration and uses a timer so long native calls can be sampled. Shared pools are counted once. Reporting does not enforce a new memory budget, and retaining the fraction avoids changing existing spill thresholds.
- Implementation sketch:
AccountingAllocatorupdates the allocation balance. The pool registry supplies a deduplicated snapshot toNative.getMemoryUsage, andCometExecIteratorschedules and formats the log.CometDriverPlugin.initalso callswarnIfMemoryPoolFractionSet, which emits the deprecation message when the setting is present. Configuration, tracing, tuning, and contributor documentation describe these changes. - Behavioral changes worth calling out: The
alloc-accountingCargo feature is removed because accounting is unconditional.spark.comet.memory.logIntervaldefaults to 10 seconds and is read from executor configuration. Zero disables periodic logging. The reported balance measures allocations, not RSS, and warnings remain advisory. Applications explicitly setting the fraction receive a deprecation warning, while its existing behavior is retained. - Suggested improvements: No additional change met the requested P1/P2 review bar.
# Conflicts: # docs/source/contributor-guide/memory_management.md # docs/source/user-guide/latest/tuning.md
andygrove
marked this pull request as ready for review
September 24, 2026 09:28
andygrove
enabled auto-merge
September 24, 2026 09:29
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Which issue does this PR close?
Part of #4576.
Rationale for this change
The tuning guide recommends setting
spark.comet.exec.memoryPool.fractionbelow1.0to leave room in the off-heap pool for native memory that Comet does not reserve. It cannot do that:greedy_unifiedignores the fraction. It is built with a pool size of 0 and asks Spark for every byte it reserves.fair_unifiedapplies it to each task's pool, limiting each memory consumer in the task tooffHeap.size * fraction / num_consumers. Spark's execution pool already limits each of N running tasks tooffHeap.size / N, which is tighter whenever more than one task is running. So on a busy executor the fraction never binds, and the tasks together can still acquire the whole pool.The only room Spark leaves for memory outside the pool is
spark.executor.memoryOverhead, and the executor memory usage log added in #6162 measures how much of it Comet needs.What changes are included in this PR?
spark.comet.exec.memoryPool.fractionis documented as deprecated, with what it actually does. Its behaviour is unchanged: several tests set it very low to force spills through thefair_unifiedper-task cap.spark.executor.memoryOverhead.How are these changes tested?
New
CometPluginsMemoryPoolFractionWarningSuitecovers the warning being logged when the setting is present and not otherwise. It is registered in both the Linux and macOS PR workflows. The rest is documentation.