Skip to content

Bridge: float vectors cross as one binary buffer, not as JSON text or one JPype call per element (stacked on #29) - #33

Open
tae898 wants to merge 2 commits into
port/functions-eventsfrom
port/floatvectors
Open

tae898 wants to merge 2 commits into
port/functions-eventsfrom
port/floatvectors

Conversation

@tae898

@tae898 tae898 commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator

Stacked on #29 (port/functions-events): the base is that branch, not main, and a merge waiter retargets this PR to main once #29 merges. Until then the diff against main also shows #29.

Ports humemai/arcadedb-embedded-python#496. A vector load spent most of its time on text: Python wrote every float as a decimal number and the engine parsed it back (insert_many), or JPype converted every list element on its own (create_vertices, Document.set). For a property declared ARRAY_OF_FLOATS the engine converts each number of a list to float anyway, so the vectors of a chunk now cross as one float32 matrix (FloatVectors.Matrix, one buffer copy) beside the JSON, and each document gets its own float[] row on the Java side. Properties that are not declared ARRAY_OF_FLOATS, and vectors that are ragged, missing or null, keep the exact JSON path.

Also in this change:

  • Database.insert_columns accepts a 2-D float32 array as a column of vectors.
  • A numpy array is accepted as a property value everywhere (Document.set, insert_many, create_vertices); it raised TypeError before.
  • The allowed_rids filter of a vector search builds its RID set in one crossing (GraphCalls.ridSet) instead of two JPype calls per RID.
  • New bridge class FloatVectors.java; DocumentBatcher, VertexBatcher and GraphCalls gain overloads, the old signatures stay.

Tests: tests/test_float_vector_bulk.py (39 tests: exact float32 equality with the engine's own list conversion on doubles a float32 cannot hold, which values keep the JSON path, every entry point, parallel mode). tests/test_vector.py and tests/test_python_callbacks.py follow the new conversion; test_a_numpy_array_is_a_return_value needs register_function, which is why this sits on #29.

Measured numbers: they come from the humemai float-vector-crossing laptop A/B study (tools/ab.py, ABBA order, one fresh process per run, 10 clean pairs per figure, 128-d float32 vectors on an ARRAY_OF_FLOATS property, 4 GB heap, one base wheel so the engine jars and the JVM are identical). The rows below are copied by script from the table that render_ab_tables.py generated from that study's ab.txt in humemai/arcadedb-embedded-python#496; they were not re-measured for this PR, and this repository has no copy of the study. Engine 26.11.1, wheel 26.11.1.dev0, cores 2 (pinned), machine x86-64 laptop, 16 cores.

Case (before = JSON text or one JPype call per element, after = one buffer; B in the verdict = after) before, median after, median after / before (95% interval) Verdict
insert_many, 100,000 dict rows, 128-d float32, chunks of 20,000 14,215 ms 2,621 ms 0.185 (0.180 to 0.191) B better by 81 to 82 percent
insert_columns, 100,000 rows, 128-d float32 609 ms 521 ms 0.862 (0.833 to 0.947) B better by 5 to 17 percent
graph_batch create_vertices, 50,000 rows, 128-d float32 3,596 ms 1,083 ms 0.300 (0.289 to 0.315) B better by 68 to 71 percent
find_nearest(k=10) with 5,000 allowed RIDs, 200 queries, 20,000 vectors 2,296 ms 569 ms 0.246 (0.235 to 0.257) B better by 74 to 76 percent
all four steps of the probe 20,605 ms 4,785 ms 0.232 (0.230 to 0.236) B better by 76 to 77 percent

The insert_columns row compares the best case of the earlier bindings (one float[] per row) with the 2-D column.

Not in this PR: user docs and the generated speed table. This repository has no user docs on this base (the Antora component is #23), and render_ab_tables.py is not here, so the table is not ported; the docs page can follow once #23 lands.

Checked locally: pre-commit (black, isort) and bandit (low severity, low confidence) clean; the touched and related tests (335 tests: float vector bulk, vector, vector SQL, insert_columns, graph batch, bulk insert, bulk JSON paths, numpy, type conversion, callbacks) pass on a wheel built from the 26.11.1.dev0 jars with this branch's bridge sources compiled by javac 25. Not run locally: the full wheel build (Docker, jlink) and the full test suite on all platforms and Python versions; CI covers those.

🤖 Generated with Claude Code

… one JPype call per element

A vector load spent most of its time on text: Python wrote every float as a decimal number and the engine parsed it back (insert_many), or JPype converted every list element on its own (create_vertices, Document.set). For a property declared ARRAY_OF_FLOATS the engine converts each number of a list to float anyway, so the vectors of a chunk now cross as one float32 matrix (FloatVectors.Matrix, one buffer copy) beside the JSON, and each document gets its own float[] row Java-side. Properties that are not declared ARRAY_OF_FLOATS, and vectors that are ragged, missing or null, keep the exact JSON path.

Also: insert_columns accepts a 2-D float32 array as a column of vectors; a numpy array is accepted as a property value everywhere (Document.set, insert_many, create_vertices; it raised TypeError before); the allowed_rids filter of a vector search builds its RID set in one crossing (GraphCalls.ridSet) instead of two per RID.

Tests: tests/test_float_vector_bulk.py (39 tests: exact float32 equality with the engine's own list conversion on doubles a float32 cannot hold, which values keep the JSON path, every entry point, parallel mode); tests/test_vector.py rid-conversion test now passes a Java RID object so the list takes the per-RID path; tests/test_python_callbacks.py numpy return value test follows the new conversion.

Ported from humemai/arcadedb-embedded-python#496. The user docs and the speed table generated there live in that repository's docs; this repository has no user docs yet.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
No conflicts. Brings in the updated functions-events branch (which now carries
main's merged changes through runtime-fixes).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
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.

1 participant