Skip to content

Conversation

@andygrove
Copy link
Member

Which issue does this PR close?

Closes #3308

Rationale for this change

NativeRowIterator reuses a single UnsafeRow object that points to native memory. The buffer is cleared on each convert() call, so any held row references become stale. Return unsafeRow.copy() to copy each row to Java heap memory.

What changes are included in this PR?

How are these changes tested?

andygrove and others added 2 commits February 2, 2026 15:26
… references

NativeRowIterator reuses a single UnsafeRow object that points to native
memory. The buffer is cleared on each convert() call, so any held row
references become stale. Return unsafeRow.copy() to copy each row to
Java heap memory.

Closes apache#3308

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@codecov-commenter
Copy link

codecov-commenter commented Feb 2, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 59.99%. Comparing base (f09f8af) to head (83303b4).
⚠️ Report is 918 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff              @@
##               main    #3367      +/-   ##
============================================
+ Coverage     56.12%   59.99%   +3.86%     
- Complexity      976     1464     +488     
============================================
  Files           119      175      +56     
  Lines         11743    16165    +4422     
  Branches       2251     2681     +430     
============================================
+ Hits           6591     9698    +3107     
- Misses         4012     5114    +1102     
- Partials       1140     1353     +213     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

The regression test was directly using Arrow classes (RootAllocator,
IntVector, VarCharVector, VectorSchemaRoot) which get shaded during
the Maven package phase. This caused NoSuchMethodError at runtime
because the test called NativeUtil.rootAsBatch() with unshaded Arrow
types, but the compiled method expected shaded types.

Refactored to use CometArrowConverters.rowToArrowBatchIter() which
handles Arrow shading internally.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@andygrove andygrove marked this pull request as ready for review February 3, 2026 16:05
@andygrove andygrove requested a review from mbutrovich February 3, 2026 16:29
currentIdx += 1

unsafeRow
unsafeRow.copy()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense... as unsafeRow can be reused. it would inflate mem usage a bit, but it is better than corrupted memory

Copy link
Contributor

@comphead comphead left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @andygrove especially for the local test, if we manage to find a solution without extra copy in future the test will help to guard against corruption issues

@andygrove
Copy link
Member Author

Running benchmark: Columnar to Row - Fixed Width Only (no strings)
  Running case: Spark (ColumnarToRowExec)
  Stopped after 24 iterations, 2031 ms
  Running case: Comet JVM (CometColumnarToRowExec)
  Stopped after 25 iterations, 2032 ms
  Running case: Comet Native (CometNativeColumnarToRowExec)
  Stopped after 25 iterations, 2059 ms

OpenJDK 64-Bit Server VM 17.0.18+8-Ubuntu-122.04.1 on Linux 6.8.0-90-generic
AMD Ryzen 9 7950X3D 16-Core Processor
Columnar to Row - Fixed Width Only (no strings):  Best Time(ms)   Avg Time(ms)   Stdev(ms)    Rate(M/s)   Per Row(ns)   Relative
-------------------------------------------------------------------------------------------------------------------------------
Spark (ColumnarToRowExec)                                   81             85           3         13.0          77.1       1.0X
Comet JVM (CometColumnarToRowExec)                          78             81           3         13.4          74.6       1.0X
Comet Native (CometNativeColumnarToRowExec)                 77             82           9         13.6          73.4       1.0X

Running benchmark: Columnar to Row - Primitive Types
  Running case: Spark (ColumnarToRowExec)
  Stopped after 22 iterations, 2029 ms
  Running case: Comet JVM (CometColumnarToRowExec)
  Stopped after 21 iterations, 2048 ms
  Running case: Comet Native (CometNativeColumnarToRowExec)
  Stopped after 22 iterations, 2019 ms

OpenJDK 64-Bit Server VM 17.0.18+8-Ubuntu-122.04.1 on Linux 6.8.0-90-generic
AMD Ryzen 9 7950X3D 16-Core Processor
Columnar to Row - Primitive Types:           Best Time(ms)   Avg Time(ms)   Stdev(ms)    Rate(M/s)   Per Row(ns)   Relative
---------------------------------------------------------------------------------------------------------------------------
Spark (ColumnarToRowExec)                               89             92           2         11.8          84.8       1.0X
Comet JVM (CometColumnarToRowExec)                      88             98          11         11.9          84.0       1.0X
Comet Native (CometNativeColumnarToRowExec)             89             92           2         11.8          85.0       1.0X

Running benchmark: Columnar to Row - String Types
  Running case: Spark (ColumnarToRowExec)
  Stopped after 13 iterations, 2012 ms
  Running case: Comet JVM (CometColumnarToRowExec)
  Stopped after 17 iterations, 2034 ms
  Running case: Comet Native (CometNativeColumnarToRowExec)
  Stopped after 15 iterations, 2092 ms

OpenJDK 64-Bit Server VM 17.0.18+8-Ubuntu-122.04.1 on Linux 6.8.0-90-generic
AMD Ryzen 9 7950X3D 16-Core Processor
Columnar to Row - String Types:              Best Time(ms)   Avg Time(ms)   Stdev(ms)    Rate(M/s)   Per Row(ns)   Relative
---------------------------------------------------------------------------------------------------------------------------
Spark (ColumnarToRowExec)                              153            155           1          6.9         145.5       1.0X
Comet JVM (CometColumnarToRowExec)                     115            120           3          9.1         110.0       1.3X
Comet Native (CometNativeColumnarToRowExec)            136            139           3          7.7         130.0       1.1X

Running benchmark: Columnar to Row - Struct Types
  Running case: Spark (ColumnarToRowExec)
  Stopped after 10 iterations, 2119 ms
  Running case: Comet JVM (CometColumnarToRowExec)
  Stopped after 9 iterations, 2158 ms
  Running case: Comet Native (CometNativeColumnarToRowExec)
  Stopped after 8 iterations, 2248 ms

OpenJDK 64-Bit Server VM 17.0.18+8-Ubuntu-122.04.1 on Linux 6.8.0-90-generic
AMD Ryzen 9 7950X3D 16-Core Processor
Columnar to Row - Struct Types:              Best Time(ms)   Avg Time(ms)   Stdev(ms)    Rate(M/s)   Per Row(ns)   Relative
---------------------------------------------------------------------------------------------------------------------------
Spark (ColumnarToRowExec)                              203            212          20          5.2         193.2       1.0X
Comet JVM (CometColumnarToRowExec)                     232            240           3          4.5         221.7       0.9X
Comet Native (CometNativeColumnarToRowExec)            267            281          19          3.9         254.9       0.8X

Running benchmark: Columnar to Row - Array Types
  Running case: Spark (ColumnarToRowExec)
  Stopped after 10 iterations, 2018 ms
  Running case: Comet JVM (CometColumnarToRowExec)
  Stopped after 13 iterations, 2063 ms
  Running case: Comet Native (CometNativeColumnarToRowExec)
  Stopped after 11 iterations, 2140 ms

OpenJDK 64-Bit Server VM 17.0.18+8-Ubuntu-122.04.1 on Linux 6.8.0-90-generic
AMD Ryzen 9 7950X3D 16-Core Processor
Columnar to Row - Array Types:               Best Time(ms)   Avg Time(ms)   Stdev(ms)    Rate(M/s)   Per Row(ns)   Relative
---------------------------------------------------------------------------------------------------------------------------
Spark (ColumnarToRowExec)                              200            202           2          5.2         190.5       1.0X
Comet JVM (CometColumnarToRowExec)                     157            159           3          6.7         149.3       1.3X
Comet Native (CometNativeColumnarToRowExec)            180            195          34          5.8         171.6       1.1X

Running benchmark: Columnar to Row - Map Types
  Running case: Spark (ColumnarToRowExec)
  Stopped after 6 iterations, 2272 ms
  Running case: Comet JVM (CometColumnarToRowExec)
  Stopped after 7 iterations, 2262 ms
  Running case: Comet Native (CometNativeColumnarToRowExec)
  Stopped after 6 iterations, 2102 ms

OpenJDK 64-Bit Server VM 17.0.18+8-Ubuntu-122.04.1 on Linux 6.8.0-90-generic
AMD Ryzen 9 7950X3D 16-Core Processor
Columnar to Row - Map Types:                 Best Time(ms)   Avg Time(ms)   Stdev(ms)    Rate(M/s)   Per Row(ns)   Relative
---------------------------------------------------------------------------------------------------------------------------
Spark (ColumnarToRowExec)                              371            379           5          2.8         354.2       1.0X
Comet JVM (CometColumnarToRowExec)                     320            323           2          3.3         305.1       1.2X
Comet Native (CometNativeColumnarToRowExec)            332            350          27          3.2         317.1       1.1X

Running benchmark: Columnar to Row - Complex Nested Types
  Running case: Spark (ColumnarToRowExec)
  Stopped after 5 iterations, 2191 ms
  Running case: Comet JVM (CometColumnarToRowExec)
  Stopped after 5 iterations, 2008 ms
  Running case: Comet Native (CometNativeColumnarToRowExec)
  Stopped after 5 iterations, 2331 ms

OpenJDK 64-Bit Server VM 17.0.18+8-Ubuntu-122.04.1 on Linux 6.8.0-90-generic
AMD Ryzen 9 7950X3D 16-Core Processor
Columnar to Row - Complex Nested Types:      Best Time(ms)   Avg Time(ms)   Stdev(ms)    Rate(M/s)   Per Row(ns)   Relative
---------------------------------------------------------------------------------------------------------------------------
Spark (ColumnarToRowExec)                              434            438           6          2.4         413.9       1.0X
Comet JVM (CometColumnarToRowExec)                     389            402          22          2.7         370.9       1.1X
Comet Native (CometNativeColumnarToRowExec)            444            466          37          2.4         423.6       1.0X

Running benchmark: Columnar to Row - Wide Rows (50 columns)
  Running case: Spark (ColumnarToRowExec)
  Stopped after 3 iterations, 2038 ms
  Running case: Comet JVM (CometColumnarToRowExec)
  Stopped after 4 iterations, 2677 ms
  Running case: Comet Native (CometNativeColumnarToRowExec)
  Stopped after 3 iterations, 2062 ms

OpenJDK 64-Bit Server VM 17.0.18+8-Ubuntu-122.04.1 on Linux 6.8.0-90-generic
AMD Ryzen 9 7950X3D 16-Core Processor
Columnar to Row - Wide Rows (50 columns):    Best Time(ms)   Avg Time(ms)   Stdev(ms)    Rate(M/s)   Per Row(ns)   Relative
---------------------------------------------------------------------------------------------------------------------------
Spark (ColumnarToRowExec)                              672            680           8          1.6         640.9       1.0X
Comet JVM (CometColumnarToRowExec)                     644            669          21          1.6         614.4       1.0X
Comet Native (CometNativeColumnarToRowExec)            668            687          19          1.6         637.3       1.0X

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Native columnar-to-row: UnsafeRow may reference freed/overwritten native memory

3 participants