sunchao commented on code in PR #5613:
URL: https://github.com/apache/datafusion-comet/pull/5613#discussion_r3910247103


##########
native/core/src/execution/memory_pools/fair_pool.rs:
##########
@@ -124,19 +162,25 @@ impl MemoryPool for CometFairMemoryPool {
 
     fn shrink(&self, _reservation: &MemoryReservation, subtractive: usize) {
         if subtractive > 0 {
-            let mut state = self.state.lock();
-            // We don't use reservation.size() here because DataFusion 53+ 
decrements
-            // the reservation's atomic size before calling pool.shrink(), so 
it would
-            // reflect the post-shrink value rather than the pre-shrink value.
-            if state.used < subtractive {
-                panic!(
-                    "Failed to release {subtractive} bytes where only {} bytes 
tracked by pool",
-                    state.used
-                )
+            {
+                let mut state = self.state.lock();
+                // We don't use reservation.size() here because DataFusion 53+ 
decrements
+                // the reservation's atomic size before calling pool.shrink(), 
so it would
+                // reflect the post-shrink value rather than the pre-shrink 
value.
+                if state.used < subtractive {
+                    panic!(
+                        "Failed to release {subtractive} bytes where only {} 
bytes tracked by pool",
+                        state.used
+                    )
+                }
+                state.used -= subtractive;
             }

Review Comment:
   [P2] Keep waiting Spark acquisitions registered during a full release
   
   Could you handle Spark's same-task wait/release contract before allowing 
this release to overlap an acquire? With `fair_unified`, two native consumers 
can now enter the same `CometTaskMemoryManager` concurrently. In a 100-unit 
executor pool, let another task hold 90 and this task hold 10. This task's next 
10-unit grow waits below Spark's 1/(2N) minimum. Freeing its last 10 units on 
another native thread removes its entry from 
`ExecutionMemoryPool.memoryForTask` and wakes the grower. The grower then 
[indexes the removed 
entry](https://github.com/apache/spark/blob/7c14a3c28b141cc97a330c4d0f5d2a6da7267f85/core/src/main/scala/org/apache/spark/memory/ExecutionMemoryPool.scala#L114)
 and throws `NoSuchElementException: key not found`. Spark's release bypasses 
the task monitor held by the waiting acquire, so that monitor does not prevent 
this interleaving. The Rust provisional reservation does not keep Spark's entry 
alive.
   
   I reproduced the failure using unchanged Spark 3.5.9 pool source with only 
logging/annotation/memory-mode scaffolding. A scheduling control modeling the 
previous serialization completed after the other task freed its memory. The 
relevant map lifecycle is also present in 4.0.4 source. This was a component 
probe plus JNI source tracing, not a full Comet query reproduction. Please make 
full releases safe while grows are pending and add a regression that exercises 
Spark's memory manager.



-- 
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