Skip to content

GH-55281: [C++][Gandiva] Release arena memory per row when no function returns a string - #55282

Open
dmitry-chirkov-dremio wants to merge 4 commits into
apache:mainfrom
dmitry-chirkov-dremio:GH-55281-gandiva-levenshtein-arena
Open

dmitry-chirkov-dremio wants to merge 4 commits into
apache:mainfrom
dmitry-chirkov-dremio:GH-55281-gandiva-levenshtein-arena

Conversation

@dmitry-chirkov-dremio

@dmitry-chirkov-dremio dmitry-chirkov-dremio commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Rationale for this change

Gandiva releases the arena per row only if some function returns a string. Functions that take the context but return other types (levenshtein, external functions) keep their arena memory until the end of the batch. See #55281.

What changes are included in this PR?

  • Release the arena per row for every function with kNeedsContext. A function without the context cannot reach the arena.
  • After each row, check an arena "used" flag. Call the reset only if the row allocated.

For someone who wants to follow along:

  • commits 1 and 3 add tests that fail
  • commit 2 is a first, narrower fix just for levenshtein
  • commit 4 replaces logic with a broader solution

Results

Memory per batch, 262,144 rows:

Test main this PR
levenshtein 36,876,288 1,085,440
External C function with arena scratch 17,858,560 1,085,440

Performance, ns/row (Apple M3, 1M rows):

Expression main this PR
divide int64 0.53 0.54
divide int32 0.54 0.54
castVARCHAR(s, 8) 6.82 6.54 (4% faster, reset is skipped)

Are these changes tested?

Yes, via new targeted test with commit history showing them being effective

Considered, not chosen

  • kUsesArena flag on arena users (commit 2): manual. A missed flag leaks silently.
  • Opt-out flag for string functions that return input pointers: a second manual flag. Gain only on very cheap casts.
  • Reset call for every context function: divide 2x slower (0.50 to 1.07 ns/row).
  • Lazy reset inside the arena (one store per row): divide int64 3x slower (0.53 to 1.49 ns/row) on Apple M3. Any per-row store costs about 1 ns there.

Are there any user-facing changes?

No.

Was AI used for this PR?

PR code and description written by:

  • Human
  • AI

Reviewed before submission by:

  • Human
  • AI

@github-actions

Copy link
Copy Markdown

⚠️ GitHub issue #55281 has been automatically assigned in GitHub to PR creator.

…ena growth

levenshtein returns int32 but uses arena memory, so the per-row arena release is never emitted for it. This test fails until that is fixed.
…shtein

Add a kUsesArena flag, set it for levenshtein, and release the arena per row for flagged functions.
@dmitry-chirkov-dremio
dmitry-chirkov-dremio force-pushed the GH-55281-gandiva-levenshtein-arena branch from d7e4af0 to 95d67a9 Compare October 27, 2026 05:49
…d string functions

An external function that takes the context and arena scratch but returns int32 still keeps its memory until the end of the batch. This test fails until that is fixed.
…unction with context

Use NeedsContext() instead of the kUsesArena flag, and skip the reset call when the row did not allocate.
@dmitry-chirkov-dremio
dmitry-chirkov-dremio marked this pull request as ready for review October 27, 2026 16:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant