gengliangwang commented on code in PR #59961:
URL: https://github.com/apache/spark/pull/59961#discussion_r4483289144


##########
sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/v2/ffi/NativeDataSource.scala:
##########
@@ -858,9 +897,21 @@ class NativePartitionReader(
   override def close(): Unit = synchronized {
     if (!closed) {
       closed = true
-      if (!reading) {
+      // Another thread may be in next, or still read the batch that next 
returned to it.
+      if (!reading && consumerDone) {

Review Comment:
   You're right, the rework isn't in yet. 3b96894 only adds the path 2 
fallback. The release logic of `NativePartitionReader` is still the one from 
050cc61: `close()` frees at once when `consumerDone`, and otherwise hands the 
release to the `releaser` pool. So the P1 still holds at the current head. To 
your three questions:
   
   1. I'll do it in this PR, not in a follow-up. This PR is what turns late 
reads from an Arrow Java exception into reads of freed memory, so I don't want 
it merged with that still open.
   2. I'm not waiting on reviewers for the GC trade-off. sarutak's case (a 
reader read to the end and then closed) gets an immediate free. Now that path 2 
copies the pass-through rows, nothing reads the buffers after `next()` returns 
false. What's left is a reader closed before the end of its stream, for example 
with a LIMIT or when a script exits early. There, the last batch's buffers and 
the child allocator wait for a GC. That's at most one batch per such reader. 
I'd take that over a late read of freed memory, and I'll note it in the class 
doc. If anyone thinks it's too much, please say so. What I still have to check 
before writing it is the two points from my earlier reply. First, that an array 
can outlive its stream: the C stream interface says their lifetimes are 
independent. Second, that an array's release callback doesn't use the task, 
because the task's context is closed when the stream is released. I'll check 
the second one against the Rust and C++ SDKs and write it into the
  `SupportsArrowStreamRead` contract.
   3. It isn't going to a follow-up, so this doesn't apply. Until the rework is 
pushed, please treat this thread as blocking.
   
   The next revision will have: `close()` frees everything at once after the 
end of the stream. Before the end, it frees the stream, the dictionaries and 
the task at once, unless a thread is inside `next()`, and a Cleaner frees the 
last batch's buffers and the allocator. A `next()` after `close()` fails. The 
consumer tracking and the `releaser` pool go away. It will also include the 
end-of-stream test I promised sarutak.
   
   <sub>Automated reply (Opus)</sub>



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