Skip to content

[MINOR][DOC] Add developer doc on Arrow columnar conversion - #13374

Merged
zhztheplayer merged 3 commits into
apache:mainfrom
FelixYBW:docs-arrow-conversion
Oct 20, 2026
Merged

zhztheplayer merged 3 commits into
apache:mainfrom
FelixYBW:docs-arrow-conversion

Conversation

@FelixYBW

@FelixYBW FelixYBW commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

What changes are proposed in this pull request?

Adds docs/developers/ArrowColumnarConversion.md (and a mkdocs nav entry), which documents:

  1. Conventions: RowType / BatchType, ConventionReq, ConventionFunc, the transition graph, and how InsertTransitions inserts transitions.
  2. Types and batch layout: VanillaRowType, VanillaBatchType, ArrowJavaBatchType (heavy batch), ArrowNativeBatchType (light batch), VeloxBatchType, VeloxCarrierRowType, with the transition graph and the composite paths the planner builds.
  3. What each transition does: LoadArrowDataExec, OffloadArrowDataExec, ArrowColumnarToVeloxColumnarExec and the row transitions, down to the JNI / Velox calls, where data is copied, and the in-place, reference-counted batch lifecycle.
  4. Example: a Velox column through an Arrow UDF: a BIGINT column from Velox through LoadArrowDataExec, ColumnarArrowEvalPythonExec and back to Velox, with the Velox buffer references and Gluten's refCnt at each step, and the release callbacks that return the memory to Velox (PlantUML sequence diagram). Also how an ArrowBuf is released depending on whether it was allocated in Java or imported through C Data, and the memory accounting of imported buffers (second PlantUML diagram).
  5. Arrow-based operators today.
  6. How to add an Arrow-based columnar operator, step by step with a checklist, using the Lance scan offload ([VL] Add Velox offload for Lance scans via Arrow C stream #12958) as the example: convention, batch ownership, validation, offload rule, component registration, tests.
  7. Ongoing work: [GLUTEN-13140][VL] Replace ArrowWritableColumnVector with Spark's ArrowColumnVector and ArrowWriter #13280, SPARK-57468 and the upstream Arrow batch ownership work.

Diagrams are PNGs under docs/image/; the PlantUML sources are included in the doc.

Based on #12289, #13140 (comment) and #13140 (comment).

How was this patch tested?

Docs only. Checked the described behavior against the code on main and the Arrow Java 15.0.0 sources, and that the relative links and images resolve.

Was this patch authored or co-authored using generative AI tooling?

Generated-by: Claude claude-opus-5-5

🤖 Generated with Claude Code

Describe how Gluten converts between rows, Spark batches, Java Arrow,
native Arrow and Velox batches today (conventions, transition graph,
what each transition does, copies, batch lifecycle), and how to add an
Arrow-based columnar operator, using the Lance scan offload as example.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 20, 2026 01:46
@github-actions github-actions Bot added the DOCS label Oct 20, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Technical descriptions and test expectations need correction, and the diagram needs MkDocs rendering support.

5 open issues
What changed in this PR

Adds a developer guide to Gluten’s Arrow conversion architecture and operator integration.

Changes:

  • Documents conventions, transitions, conversion costs, and batch ownership.
  • Provides Lance-based integration steps, testing guidance, and ongoing-work references.
  • Adds the guide to MkDocs navigation.
File Description
mkdocs.yml Adds the developer-guide navigation entry.
docs/​developers/​ArrowColumnarConversion.md Explains Arrow conversions and operator integration.

Review effort: Balanced

Comment on lines +77 to +78
```mermaid
flowchart LR
Comment on lines +131 to +133
| Velox → Java Arrow (`load`) | No copy | Copied: Velox's `StringView` layout is exported as an Arrow string array, since Arrow string views aren't enabled | Flattened (copied) |
| Java Arrow → native Arrow (`offload`) | No copy | No copy | Not used |
| Native Arrow → Velox | No copy | A new `StringView` buffer is built (strings of 12 bytes or less are inlined) | Not used |
| Operator | Batch type in → out | How it's planned |
|---|---|---|
| `ColumnarArrowEvalPythonExec` (Arrow / pandas UDFs) | Java Arrow → Java Arrow | Gluten's own operator and Python runner, from `OffloadSingleNodeRules` |
| `ColumnarPartialProjectExec`, `ColumnarPartialGenerateExec` | Velox → Velox | Load to Java Arrow inside the operator, evaluate the Spark expressions row by row, and write the results with `ArrowProjection` |
| `ColumnarArrowEvalPythonExec` (Arrow / pandas UDFs) | Java Arrow → Java Arrow | Gluten's own operator and Python runner, from `OffloadSingleNodeRules` |
| `ColumnarPartialProjectExec`, `ColumnarPartialGenerateExec` | Velox → Velox | Load to Java Arrow inside the operator, evaluate the Spark expressions row by row, and write the results with `ArrowProjection` |
| `ColumnarRangeExec` | – → Java Arrow | Builds `ArrowWritableColumnVector`s in the JVM |
| `VeloxRDDScanTransformer`, `VeloxLocalTableScanTransformer` | – → Velox | Write rows into `ArrowWritableColumnVector`s, then convert them to Velox inside the operator |
Comment on lines +283 to +284
- The node is offloaded, and the plan has the expected transitions: none to a vanilla row consumer,
and `OffloadArrowDataExec` → `ArrowColumnarToVeloxColumnarExec` to a Velox consumer.
- Add section 4: a Velox BIGINT column through LoadArrowData, an Arrow
  UDF and back to Velox, with the reference counts at each step and the
  release callbacks back to Velox's memory (PlantUML sequence diagram).
- Explain how an ArrowBuf is released depending on whether it was
  allocated in Java or imported through C Data, and the memory
  accounting of imported buffers (second PlantUML diagram).
- Replace the mermaid transition graph with rendered images.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 20, 2026 07:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Copilot review overview

8 open issues

Review effort: Lite

Comment on lines +25 to +28
| Concept | Code | Meaning |
|---|---|---|
| `Convention.RowType` | `gluten-core/.../transition/Convention.scala` | A row format. `VanillaRowType` is Spark's `InternalRow`; `None` means the node outputs no rows |
| `Convention.BatchType` | same | A columnar batch format. `VanillaBatchType` is Spark's `ColumnarBatch`; `None` means no batches |
Comment on lines +1 to +6
---
layout: page
title: Arrow Columnar Conversion
nav_order: 21
parent: /developer-overview/
---
Comment on lines +129 to +132
This follows one fixed-width column, a `BIGINT` column `x`, through
`Velox op → LoadArrowDataExec → ColumnarArrowEvalPythonExec → OffloadArrowDataExec →
ArrowColumnarToVeloxColumnarExec → Velox op`, for a query such as `SELECT x, f(x)` with a pandas or
Arrow UDF `f`. .
Copilot AI balanced review requested due to automatic review settings October 20, 2026 07:22

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Comment on lines +25 to +31
| Concept | Code | Meaning |
|---|---|---|
| `Convention.RowType` | `gluten-core/.../transition/Convention.scala` | A row format. `VanillaRowType` is Spark's `InternalRow`; `None` means the node outputs no rows |
| `Convention.BatchType` | same | A columnar batch format. `VanillaBatchType` is Spark's `ColumnarBatch`; `None` means no batches |
| `ConventionReq` | `ConventionReq.scala` | What a parent requires from each child: `Any` or `Is(type)`, for rows and for batches |
| `Transition` | `Transition.scala`, `TransitionGraph.scala` | An edge of the graph: a function `SparkPlan => SparkPlan` that wraps the child with a converting operator, or `Transition.empty` when the data is already compatible |
| `ConventionFunc` | `ConventionFunc.scala` | Derives the convention of any plan, including vanilla Spark plans and plans through `QueryStageExec` / `ReusedExchangeExec` |
Comment on lines +129 to +132
This follows one fixed-width column, a `BIGINT` column `x`, through
`Velox op → LoadArrowDataExec → ColumnarArrowEvalPythonExec → OffloadArrowDataExec →
ArrowColumnarToVeloxColumnarExec → Velox op`, for a query such as `SELECT x, f(x)` with a pandas or
Arrow UDF `f`. .
- **Imported through C Data** (`Data.importIntoVectorSchemaRoot`): the buffer has a
`ForeignAllocationManager`, whose `release0()` calls `ReferenceCountedArrowArray.release()`. When
the last buffer of the imported array is released, it calls the array's C `release` callback,
here Velox's. It's the `release` member function of Arrow C_data interface:
@zhztheplayer
zhztheplayer merged commit 0ef7c93 into apache:main Oct 20, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants