You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit abb4830
Browse filesBrowse the repository at this point in the historyBrowse files
feat(spark): bound Arrow write batches by bytes (#62)
## Summary
Closes#58.
Adds optional `vortex.write.batch.bytes`: after each complete row, the
writer flushes when the open batch's Arrow allocations reach this
positive byte threshold or the existing row limit. Unset preserves
row-only batching. A single row or buffer growth can exceed the
threshold; it is not a bound on total process memory.
## Changes
- Count the open batch's unique backing allocations, including nested
buffers and allocation rounding. Previous batches retained or released
by native code do not affect the measurement; subtracting an allocator
baseline would undercount when older batches are released.
- Cache the measurement until Arrow allocates again, avoiding a
wide-schema traversal after every row. Install tracking only when the
byte option is set.
- Reset capacity estimates after a byte-triggered flush so one oversized
row does not force every later small row into its own oversized batch.
- Validate positive long byte values on the driver, with
case-insensitive lookup and clear errors for malformed, zero, negative
and overflowing values. Document the option and its limits.
- Add regressions for row/byte limits, oversized and nested rows,
subsequent small-row batching, shared allocations, old-batch releases,
and string/binary preservation during measurement.
## Complete review
Completed four independent reviews for reuse, quality, efficiency and
correctness. Revalidated and applied the worthwhile findings: use
non-mutating Arrow buffer accessors during unfinished batches, reset
oversized capacity estimates, and request ordered scans in exact-order
round-trip tests. No unresolved review findings remain.
## Validation
- Targeted tests: **52 passed on Spark 3.5 / Scala 2.12 and 52 passed on
Spark 4.0 / Scala 2.13**, including the native writer memory stress
tests.
- Java compilation with Error Prone and `-Werror` passed.
- `./gradlew spotlessJavaCheck` and `:vortex-spark-4.0_2.13:javadoc`
passed.
- `git diff --check` passed.
- The full Spark variant matrix and workspace suite were not run.
I used AI tools to help implement and review this change.
Signed-off-by: Christopher Wirt <[email protected]>
|`batch.size`|`8192`| Rows buffered per write batch; range 1–65536. Each string or binary field of a batch must fit in 2 GiB, so lower it for values over about 256 KB. |
139
139
|`vortex.write.batch.size`| — | Rows buffered per write batch for Vortex alone, overriding `batch.size`. |
140
+
|`vortex.write.batch.bytes`| — | Positive byte threshold for the open batch's Arrow allocations; flush after a row reaches it or the row limit, whichever comes first. Unset disables byte-based flushing. |
140
141
|`vortex.listLayout`|`false`| Store array columns in the unstable list layout; see below. |
141
142
143
+
The byte threshold includes nested buffers and Arrow's allocation rounding. It is checked after
144
+
each complete row, so one row or a buffer growth can exceed it. It bounds batching rather than
145
+
total process memory: native code may retain earlier batches and allocate compression buffers.
146
+
142
147
By default an array column is stored as whole chunks, so reading one field of the structs in an
143
148
array reads every field of them. With `vortex.listLayout` set to `true`, the writer stores each
144
149
array's offsets, nulls, and elements apart, and splits struct elements into one column per field,
0 commit comments