Skip to content

Glue: JSON text as an intermediate on bulk and per-row paths, ten ranked candidates (none timed yet) #388

Open

Description

@tae898

Several paths of both wheels still put data into JSON text on the Java side and parse it again in Python. For bulk, typed or wide data that costs a text format, a parse and one dict per row, and the columnar routes of #331, #335 and #383 show what the binary route buys. I went through every place of the glue that uses JSON as an intermediate (a code read of main at 65e7c8f: 42 uses classified from 338 grep hits in 29 files) to see which ones are worth removing.

None of this is timed. Every cost named here is a number of crossings or per-row work read from the code, so nothing below is a speed claim. Each item gets its own measured table and a pre-registered A/B (ABBA, A/A control, against the released wheel) before its pull request, as for #382 to #385.

17 of the 42 uses sit on a bulk or per-row path. Ten are worth the work, ranked by how much data goes through them and how small the fix is:

rank wheel site on main what the JSON carries when replacement rebuild check first
1 JVM src/arcadedb/core.py:948 insert_many rows as one JSON text per chunk (10,000 rows), tagged values for date, datetime, Decimal, bytes, numpy and pandas scalars; float vectors... per chunk of 10,000 rows route homogeneous chunks through rows_to_columns and DocumentBatcher.insertColumns (exists); keep JSON for shapes columns cannot carry none (PY) yes, plus a stored-type differential test
2 native src/arcadedb/_native/database.py:648 row count (count() walks the whole result) per count() call; O(rows) arcadedb_n_count returning a long; PY partial: count len(batch) without building NativeResult native image for full no, the loop is the evidence
3 native native/src/main/java/org/humemai/nativelib/ArcadeNative.java:205 transaction state {ok, active, depth, commits} per begin, commit, rollback, is_transaction_active, stack mark return one long (active bit, depth, commits packed) from arcadedb_n_tx native image no, counts are the evidence; measure only to size the win
4 native src/arcadedb/_native/colframes.py:160 head of a columnar read: up to 256 JSON-decoded rows re-packed into a frame with a Python-written JSON header once per to_arrow/to_columns/to_dataframe/to_polars call ask Java for frame 1 directly (arcadedb_n_next_col from the first call), retire _head_frame native image + PY yes
5 native src/arcadedb/_native/schema_objects.py:331 approximate vector search: the query vector as a JSON list of d numbers, hits as a JSON list of [rid, score] per search arcadedb_n_vindex_bin taking a float32 pointer and count; hits as one packed buffer native image yes: how often approximate is called in the benchmark lanes
6 native native/src/main/java/org/humemai/nativelib/NativeCodec.java:83 query and command result rows (property dict per row, plus a meta array per row: rid, type, v/e/d) first reply up to 256 rows (_FIRST_BATCH), then 2048 rows per crossing (_NEXT_BATCH); per... binary row batches (frame per batch decoded to column lists, rows built by zip) for typed or wide results; keep JSON for narrow plain rows native image yes: json.loads is C, zip-of-columns is Python per row
7 native src/arcadedb/_native/extras.py:193 GraphBatch create_vertices: rows as JSON, RIDs back as a JSON list of text per chunk (commit_every rows) frame (insert_cols layout) in, packed long[] of RIDs back native image yes
8 native src/arcadedb/_native/extras.py:575 async create_record: one JSON op {type, kind, props} per record, plus callbacks per record a create_records batch entry taking a frame; or buffer in Python and use insert_parallel native image no, crossings are the evidence
9 JVM src/arcadedb/graph_batch.py:262 GraphBatch create_vertices: rows as JSON text, RIDs back as one ';'-joined text per chunk (_BULK_CHUNK rows) a ColumnBatcher-style typed insert for vertices (DocumentBatcher.insertColumns already builds vertex types) none (PY) or bridge jar yes
10 both native/src/main/java/org/humemai/nativelib/ColumnFrames.java:322 the json column kind inside binary column frames (nested lists, maps, RIDs, embedded documents, mixed-type columns): one tagged JSON array per column per frame, per cell of such a column add column kinds: rid (two int64), list of int64/float64 (ragged offsets), keep json for the rest native image and bridge jar yes

Also found, not in the first audit: the query vector of an approximate vector search crosses as a JSON list (rank 5), and the json cell kind inside binary frames (rank 10) makes RID, list and map columns go through text. arcadedb_command in ArcadeLib.java has no Python caller and can go.

What stays: error replies, control and configuration messages, frame headers and column specs (once per call or per failure), statement parameters (small, and float32 vectors already go binary), the JVM to_dict and to_list reads where the code comments say JSON is the cheaper container on JPype (only the object hook is removable, that is #382), and the shapes that a column cannot carry (widen the columnar path first). The JSON that a caller asks for (to_json_list, iter_json_batches, to_json) never goes.

Rank 3 is #384, and rank 4 is the second part of #381. The rest has no pull request yet. I take them in the order of the table, the first ones needing no native rebuild, and I post the A/B of each here.

Related: #315, #381.

Metadata

Metadata

Assignees

Labels

jvmThe arcadedb-jvm package (JPype build)nativeThe arcadedb package (native library build)performanceSpeed or memory of the bindings, with a measurementpythonPull requests that update python codevectorVector indexes and find_nearest

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions