peterxcli commented on PR #5046:
URL: 
https://github.com/apache/datafusion-comet/pull/5046#issuecomment-5207910547

   @andygrove pretty thanks for another round of review!
   
   > `writeColUnsafe` is only in-bounds when the writer came from `create(root, 
capacity)`, and nothing connects those two. `RowArrowReader`, 
`CometArrowConverters`, and `ConstantColumnVectors.materialize` all build 
writers with the plain `create(root)` and its 3970 default, so pointing any of 
them at the new methods later would compile fine and write out of bounds.
   > Have you considered folding the capacity guarantee into `writeCol` 
instead? The base `writeCol` already calls 
`valueVector.setInitialCapacity(inputNumElements)`, and as far as I can tell 
that call does nothing at that point, since `setInitialCapacity` only affects 
the next `allocateNew()` and we are already past it. If a 
`FixedWidthArrowFieldWriter` override replaced it with something like:
   > ```scala
   > while (valueVector.getValueCapacity < inputNumElements) 
valueVector.reAlloc()
   > ```
   > then the non-resizing setters would always be in-bounds by construction. 
That would let `writeColUnsafe` and `writeColNoNullUnsafe` go away entirely, 
and `ConstantColumnVectors.materialize` would pick up the same win, which 
matters because it runs per batch for partition and `_metadata` constants.
   
   Addressed, this is brilliant. great cleanup.
   
   > Could the capacity check in `writeColUnsafe` be `require` rather than 
`assert`? `NativeBase.setArrowProperties()` sets 
`arrow.enable_unsafe_memory_access=true` whenever debug mode is off, which is 
the default, and that disables Arrow's own `ArrowBuf` bounds checks. So that 
line is the only guard against an out-of-bounds native write if a writer ever 
reaches there under-allocated. It runs once per column per batch and 
`getValueCapacity` is just a cached field read, so making it unconditional 
should not show up in the numbers.
   
   make sense, changed assert to `while (valueVector.getValueCapacity < 
inputNumElements) { valueVector.reAlloc() }`
   
   > Since `create(root, capacity)` exists now, is there a reason to leave 
`RowArrowReader` on the plain `create(root)`? It knows `maxRecordsPerBatch`, so 
today it allocates 3970 and reallocs to 8192 on every batch. That path is the 
fallback for any child that does not support columnar output, so it may well be 
hit more often than the columnar one.
   
   you're right, remaining usage are only existed in test code. I've completely 
removed the plain `create(root)` and change its caller code.
   
   > Also, the class doc on `SparkColumnarArrowReader` still says the rows go 
in "via `ArrowWriter.writeCol`". Worth updating to match.
   
   class doc on `SparkColumnarArrowReader` is updated.
   
   > benchmark: the A/B numbers are exactly what I wanted ... . ... there is 
nothing for Spark to Arrow conversion.
   
   Added as `CometArrowWriterBenchmark.scala`.
   
   > `nullableArrow.getValueCapacity should be >= numRows` would pass on the 
old resizing path too, since `reAlloc` grows the vector past `numRows` either 
way. The assertion that actually pins the new behavior is `allocatedBytes 
shouldBe allocator.getAllocatedMemory`, and its intent is not obvious from 
reading it. A short comment saying that a realloc would make cumulative 
allocations exceed live allocated memory would help whoever touches this next.
   
   Added into existing "pre-sized Arrow writer avoids fixed-width 
reallocations" test case in `CometArrowStreamSuite.scala`.
   
   > It might also be worth extending this beyond `IntVector`. `BooleanWriter` 
and `DecimalWriter` have the only non-trivial `setValueUnsafe` bodies, 
`BitVector` writes bits into the value buffer rather than fixed-width slots, 
and 
   
   Added into existing "pre-sized Arrow writer avoids fixed-width 
reallocations" test case in `CometArrowStreamSuite.scala`.
   
   > `DecimalWriter`'s `changePrecision`-returns-false branch calling 
`setNullUnsafe` is not exercised anywhere I can find. Comparing all `numRows` 
values against the input instead of three spot checks would also catch an 
off-by-one in the new loops.
   
   Added in `CometArrowStreamSuite.scala` as a new "fixed-width decimal write 
clears validity on precision overflow" test case.
   
   > Lastly, given the point about `arrow.enable_unsafe_memory_access` above, a 
test that a mis-sized writer fails loudly would be worth having. Build one with 
`create(root)`, then write more than 3970 rows.
   
   Added in `CometArrowStreamSuite.scala` as a new "fixed-width column write 
grows an undersized vector" test case.


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