Skip to content

Add Jmh benchmarks along with corresponding rust benchmarks#8597

Open
robert3005 wants to merge 4 commits into
developfrom
mp/jni-bench
Open

Add Jmh benchmarks along with corresponding rust benchmarks#8597
robert3005 wants to merge 4 commits into
developfrom
mp/jni-bench

Conversation

@robert3005

Copy link
Copy Markdown
Contributor

Add Jmh benchmarks for java bindings with corresponding rust version of those
benchmarks

@robert3005 robert3005 requested a review from a team June 25, 2026 18:21
@codspeed-hq

codspeed-hq Bot commented Jun 25, 2026

Copy link
Copy Markdown

Merging this PR will improve performance by 12.06%

⚠️ Unknown Walltime execution environment detected

Using the Walltime instrument on standard Hosted Runners will lead to inconsistent data.

For the most accurate results, we recommend using CodSpeed Macro Runners: bare-metal machines fine-tuned for performance measurement consistency.

⚡ 2 improved benchmarks
✅ 1595 untouched benchmarks
⏩ 4 skipped benchmarks1

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Simulation bitwise_not_vortex_buffer_mut[128] 244.4 ns 215.3 ns +13.55%
Simulation bitwise_not_vortex_buffer_mut[1024] 304.7 ns 275.6 ns +10.58%

Tip

Curious why this is faster? Comment @codspeedbot explain why this is faster on this PR, or directly use the CodSpeed MCP with your agent.


Comparing mp/jni-bench (b0360cb) with develop (f8b18d9)

Open in CodSpeed

Footnotes

  1. 4 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@robert3005 robert3005 added the changelog/chore A trivial change label Jun 25, 2026
mprammer and others added 4 commits July 4, 2026 21:07
New `vortex-jni-bench` module (JMH) that stresses the vortex-jni read boundary — JNI plus the
Arrow C Data Interface — which is the path an Iceberg FormatModel takes to read Vortex from the
JVM. Three query shapes (full scan, projection, selective filter) over a synthetic six-column
table, consumed column-at-a-time so the numbers reflect format/boundary cost rather than per-row
JVM allocation. Includes a batch-granularity diagnostic (Vortex coalesces to ~64K-row read
batches regardless of write chunk) and a README with run instructions.

Must run against a --release native lib (VORTEX_SKIP_MAKE_TEST_FILES=true to preserve it). v2
TODO: a native Rust criterion read of the same file as a floor, to quote boundary overhead vs
native.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: mprammer <martin@spiraldb.com>
…ix units, add guards

A codex-run gauntlet (fresh/correctness/maint) flagged the first cut as overclaiming relative
to what it measured. This commit fixes that:

- Isolate native pushdown from JVM-side work: add projectionControl (full scan, consume id,y
  in Java) and filterControl (full scan, filter cat='alpha' in Java). The pushdown speedup is
  now projection-vs-projectionControl (~4.1x) and selectiveFilter-vs-filterControl (~4.6x),
  not the confounded ~6x-vs-fullScan. (M2)
- fullScan now consumes all six columns at the buffer level (z, cat, tag added), so the
  "all-six-column scan" number is honest (~40M rows/s). (M1)
- @OperationsPerInvocation(ROWS) so JMH reports input rows/s directly, not scans/s. (M3)
- @setup validates the file before measuring: exact row count, cat='alpha' returns ROWS/|CATS|,
  projection schema is exactly [id,y] — fast garbage can't be cited. (M5)
- Gradle guard fails the jmh task unless VORTEX_SKIP_MAKE_TEST_FILES=true, so a plain run can't
  silently rebuild + measure the debug lib. (M6)
- @threads(1); tag carries a 10% null rate; README documents the synthetic-data caveats.

Read path returns string columns as VarCharVector (Utf8), not ViewVarCharVector — matches the
existing TestMinimal read path. Native floor for a boundary-overhead % remains the v2 TODO (M4).

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: mprammer <martin@spiraldb.com>
Adds a native-Rust read "floor" for the vortex-jni read-boundary benchmark so
Appendix B can quote JNI+Arrow-C-boundary throughput against a Rust-native floor
from one reproducible box.

- vortex-jni/src/bin/floor.rs: mirrors the JNI read path (session -> file -> scan
  -> array stream -> execute_arrow) on the same CurrentThreadRuntime the JNI lib
  uses, stopping before the Arrow C export / JNI / JVM. Reports rows/s for
  fullScan / projection(id,y) / selectiveFilter(cat='alpha'), normalized by the
  file row count to match JMH's @OperationsPerInvocation. Validates row counts.
- VortexJniReadBenchmark: when VORTEX_JNI_BENCH_FILE is set, write+keep the table
  at that path (instead of a deleted temp file) so the floor reads the
  byte-identical file. Default behavior unchanged.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: mprammer <martin@spiraldb.com>
…ruption

underflow.rs reproduces whole-row data corruption in the vortex-jni Arrow-C
write path: a multi-chunk write of Arrow-imported variable-width (Utf8/Utf8View)
columns with a reused VectorSchemaRoot and an uneven final chunk corrupts the
tail of full-size chunks (strings -> "", ints -> 0). A pure-Rust write of the
same data is clean; the JMH read bench's `cat = 'alpha'` filter consequently
under-counts (111,168 vs the expected 125,000 = ROWS/16).

Run: cargo run -p vortex-jni --bin underflow   (knobs: UF_ROWS / UF_CHUNK / UF_VIEW)

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: mprammer <martin@spiraldb.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog/chore A trivial change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants