-
Notifications
You must be signed in to change notification settings - Fork 4k
ARROW-16673: [Java] C data interface: Allow ownership transferring for imported buffer #13248
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -104,7 +104,21 @@ public ArrowBuf deriveBuffer(ArrowBuf sourceBuffer, long index, long length) { | |
|
|
||
| @Override | ||
| public OwnershipTransferResult transferOwnership(ArrowBuf sourceBuffer, BufferAllocator targetAllocator) { | ||
| throw new UnsupportedOperationException(); | ||
| ArrowBuf targetArrowBuf = this.deriveBuffer(sourceBuffer, 0, sourceBuffer.capacity()); | ||
| targetArrowBuf.readerIndex(sourceBuffer.readerIndex()); | ||
| targetArrowBuf.writerIndex(sourceBuffer.writerIndex()); | ||
|
|
||
| return new OwnershipTransferResult() { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can OwnershipTransferNOOP be used here? |
||
| @Override | ||
| public boolean getAllocationFit() { | ||
| return true; | ||
| } | ||
|
|
||
| @Override | ||
| public ArrowBuf getTransferredBuffer() { | ||
| return targetArrowBuf; | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| @Override | ||
|
|
||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -99,6 +99,7 @@ | |
| import org.apache.arrow.vector.types.pojo.Field; | ||
| import org.apache.arrow.vector.types.pojo.FieldType; | ||
| import org.apache.arrow.vector.types.pojo.Schema; | ||
| import org.apache.arrow.vector.util.TransferPair; | ||
| import org.junit.jupiter.api.AfterEach; | ||
| import org.junit.jupiter.api.BeforeEach; | ||
| import org.junit.jupiter.api.Test; | ||
|
|
@@ -704,6 +705,37 @@ public void testImportReleasedArray() { | |
| } | ||
| } | ||
|
|
||
| @Test | ||
| public void testTransferImportedBuffer() { | ||
| VectorSchemaRoot imported; | ||
|
|
||
| // Consumer allocates empty structures | ||
| try (ArrowSchema consumerArrowSchema = ArrowSchema.allocateNew(allocator); | ||
| ArrowArray consumerArrowArray = ArrowArray.allocateNew(allocator)) { | ||
| try (VectorSchemaRoot vsr = createTestVSR()) { | ||
| // Producer creates structures from existing memory pointers | ||
| try (ArrowSchema arrowSchema = ArrowSchema.wrap(consumerArrowSchema.memoryAddress()); | ||
| ArrowArray arrowArray = ArrowArray.wrap(consumerArrowArray.memoryAddress())) { | ||
| // Producer exports vector into the C Data Interface structures | ||
| Data.exportVectorSchemaRoot(allocator, vsr, null, arrowArray, arrowSchema); | ||
| } | ||
| } | ||
| // Consumer imports vector | ||
| imported = Data.importVectorSchemaRoot(allocator, consumerArrowArray, consumerArrowSchema, null); | ||
| } | ||
|
|
||
| try (BufferAllocator targetAllocator = allocator.newChildAllocator("transfer allocator", 0, Long.MAX_VALUE)) { | ||
| for (FieldVector fieldVector : imported.getFieldVectors()) { | ||
| int cnt = fieldVector.getValueCount(); | ||
| // Transfer buffer ownerships. Should not report any error | ||
| TransferPair transferPair = fieldVector.getTransferPair(targetAllocator); | ||
| transferPair.transfer(); | ||
| ValueVector to = transferPair.getTo(); | ||
| assertEquals(cnt, to.getValueCount()); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does targetAllocator report for allocated bytes after the transfer? |
||
| } | ||
| } | ||
| } | ||
|
|
||
| private VectorSchemaRoot createTestVSR() { | ||
| BitVector bitVector = new BitVector("boolean", allocator); | ||
|
|
||
|
|
||
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it expected that
targetAllocatorisn't involved in this method at all?Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kind of. I would understand this as the original design of
CDataReferenceManagernot to bind itself to any allocator.To me it would be great if we take some time to find if it is possible to make some refactors on ReferenceManager and BufferLedger to decouple allocator instance from the base interface ReferenceManager. Sounds OK to me that a native memory block doesn't "belong to" any Java side allocator.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It concerns me somewhat that the method doesn't perform its stated purpose: "Transfer the memory accounting ownership of this ArrowBuf to another allocator", but I also understand what you're saying about the referenceManager not binding itself to any allocator: the getAllocator() method in this class always returns null. Even so, I wonder if it's not better to give this operation a name that matches the functionality better.
I noticed also that this implementation is very similar to
public ArrowBuf retain(ArrowBuf srcBuffer, BufferAllocator targetAllocator)which also has an unused bufferAllocator argument. The main difference between the two methods seems to be that the retain() implementation increments the reference count, while this method does not. It also returns the newly derived buffer directly, rather than wrapped in a OwnershipTransferResult. But since the flag in the result here is alwaystrue, it doesn't seem to add too much.Are you trying to make the CDataReferenceManager usable in code that supports other ReferenceManager implementations? If not, I guess I would just ask that you confirm that a variation without the reference count increment is needed, and that it should have this signature instead of something more descriptive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be helpful for a project I'm currently working on. For
CDataRefereneceManagerspecifically, though, do you know if there's currently any way to copy aValueVector? I'm essentially trying to clone a VectorSchemaRoot that's read from a Parquet file into aRootAllocator.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adzcai Is the 'This' that would be helpful is the new method that doesn't increment the reference count, or some other aspect of the PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does seem like this might be a partial fix, that might have unintended consequences. It seems like this was already discussed on the main page of the PR was there any resolution here?