Visitar URL original
Export and import of a database: time, memory and exactness, native and JVM wheel · Issue #369 · ArcadeData/arcadedb-python · GitHub
Skip to content

Export and import of a database: time, memory and exactness, native and JVM wheel #369

Open

Description

@tae898

We will export and import databases often now: the tower's nightly dump, the per-host agents' state files, restore drills, and moving datasets between the laptop and the mini. The only recorded problem with EXPORT DATABASE and IMPORT DATABASE is correctness (ArcadeData/arcadedb#8871: infinite FLOAT and DOUBLE values and DECIMAL precision were lost, since closed). Nobody has measured their speed or memory, and nobody has checked that a round trip is exact for the data we actually have.

Questions

  1. How long and how much memory do EXPORT DATABASE and IMPORT DATABASE need per million records, for documents, for vertices with edges, and for a vector property?
  2. What does the file cost on disk, plain and compressed?
  3. Is the round trip exact: record counts per type, the content of every property, the edges, and the special values (infinite and NaN floats, DECIMAL scale, dates, lists, embedded maps)?
  4. How do they compare with loading the same data through insert_many or Arrow, and with BACKUP DATABASE and a restore?
  5. Native wheel or JVM wheel.

Design

  • Data: synthetic and deterministic. 10,000, 100,000, and 1,000,000 vertices, 5 edges per vertex, a property mix that includes the special values above, and a variant with a 768-dimension float32 vector column.
  • Wheels: arcadedb (native) and arcadedb-jvm, both at 26.11.1.post2, JDK 25 for the JVM wheel.
  • Host: the laptop first, untimed and directional. The mini only if a finding matters.
  • Repetitions: 3 per cell. Figures: wall time, peak resident memory, file size. Correctness: counts per type and an order-independent content digest before and after, with a rule that any difference is a failure listed per property and per type, never rounded away.
  • Pre-registered rules, a README and a harness follow the layout of the other bindings studies; numbers are checked with numcheck.py before anything is posted.

Acceptance

  • The harness and its rules are written and a smoke run at 10,000 vertices passes.
  • The laptop run is queued and its results are posted here.
  • Each failed round trip becomes an upstream issue with a Java repro on the engine API.
  • The docs of the bindings say how long a dump takes per million records and what it needs in memory.

Activity

  1. self-assigned this
    on Nov 11, 2026
  2. added
    jvmThe arcadedb-jvm package (JPype build)
    nativeThe arcadedb package (native library build)
    performanceSpeed or memory of the bindings, with a measurement
    pythonPull requests that update python code
    vectorVector indexes and find_nearest
    on Nov 11, 2026
  3. added this to the 26.12.1 milestone on Nov 11, 2026
  4. tae898 commented on Nov 11, 2026

    @tae898
    CollaboratorAuthor

    The harness and its pre-registered rules are written, and the smoke run at 10,000 vertices passed on both wheels (26.11.1.post2, engine build a3a5d12457): 90 comparisons passed, 0 failed, and every negative control I planted (one changed property value, one deleted record, per shape and wheel) was caught, so a round trip that loses data cannot score as a pass. A probe of 27 single-value cases round-trips exactly on both wheels, including infinite and NaN floats, which agrees with ArcadeData/arcadedb#8871 being closed. BACKUP DATABASE can be measured too: pointing arcadedb.server.backupDirectory at the scratch folder is in force on both wheels. One repetition at 10,000 vertices is a smoke, not a result; the queued runs are untimed and directional, 10,000 and 100,000 vertices first, 3 repetitions each, and the 1,000,000 cells after I have read the 100,000 memory.

    Three things from the smoke that I will check at size before I claim anything:

    • The vector column makes export slow. For 10,000 vertices with a 768-dimension float32 vector, EXPORT DATABASE took 8.93 s on the native wheel and 10.25 s on the JVM wheel, against 0.48 s and 1.17 s for the same vertices and edges without the vector, and the plain JSONL is 96 MB against 10 MB. Import goes from 1.26 s to 4.52 s (native) and from 2.92 s to 4.99 s (JVM).
    • The native wheel cannot read a vector into a query result without numpy: a SELECT of a record with an ARRAY_OF_FLOATS property raised ModuleNotFoundError: No module named 'numpy' in an environment with only the wheel, and numpy is not a dependency of the wheel.
    • The same Python documents export to different text on the two wheels: plain JSONL of the document shape is 5,157,335 bytes when the records were loaded through the native wheel and 4,068,321 bytes through the JVM wheel (1.27 times), because the native wheel's records carry a per-record type hint for list and map elements. The values compare equal after the round trip, so I read it as a stored-type difference, which the 100,000 run will show again or not.

    Next: the 10,000 and 100,000 runs, then a Java repro on the engine API for anything that fails or looks wrong at size.

  5. tae898 commented on Nov 11, 2026

    @tae898
    CollaboratorAuthor

    Verdict: PASS at 10,000 vertices, INVALID at 100,000 vertices under my pre-registered rule R7, so I do not claim a pass at the larger size.

    At 10,000 vertices every rule held on both wheels. At 100,000 vertices every comparison of counts, content, schema, load and restore also agreed on both wheels (table below), but R7 plants one change in a copy of the source database and requires the comparison to report exactly one difference. The deleted-record control was caught as exactly one at both sizes. The control that adds 1 to one p_long was caught at 10,000 vertices (1 of 10,000 records, in that property and no other), but the harness keeps per-record hashes only up to 50,000 vertices, so at 100,000 vertices all 12 of those controls reported p_long: ? of 100,000 (a digest difference in the right property and in no other, with the number of records unknown). As written, the rule calls that not caught, marks the check as not trusted, and voids every PASS at that size. A rule change after the first run above 10,000 vertices is a new study, so I leave the rule as it is. I have queued a rerun of the controls at 50,000 vertices with the same seed, 1 repetition and all six cells on both wheels (queue lines eix-native-50k-ctl and eix-jvm-50k-ctl, new output directories, nothing of the finished runs touched), and I will post its result here as an addendum. At 50,000 vertices the per-record hashes are kept, so it can close R7 at that size only; it does not change the 100,000-vertex verdict.

    Method. Laptop, Intel(R) Core(TM) Ultra X9 388H, Linux 7.0.0, Python 3.12.13, nice -n 19, cores 12 to 15 (the four low-power cores), untimed and directional, in a lane that no other queued job shares. Wheels arcadedb==26.11.1.post2 (native) and arcadedb-jvm==26.11.1.post2 (JDK 25.0.5, max heap 2g at 10,000 vertices and 4g at 100,000 vertices), engine 26.11.1 build a3a5d12457, engine defaults. Data is synthetic and deterministic: documents, or vertices with 5 edges per vertex, or the same with a 768-dimension float32 vector, each in a mix variant (infinite and NaN floats, -0.0, extremes, DECIMAL scales 0 to 12, dates, nested lists and maps, a NUL, unicode) and a fin variant (finite substitutes in the same slots). 3 repetitions per cell, every phase in its own fresh process. Time is time.perf_counter around the EXPORT DATABASE (SQL) or IMPORT DATABASE call only; peak memory is VmHWM of that process right after the call; a record is a document, or a vertex or an edge. Exactness compares, per type and property, an order-independent digest of every record read back from the source database, from the imported database, and from a restored BACKUP DATABASE archive. BACKUP DATABASE is written through arcadedb.server.backupDirectory, which was in force on every backup row. All times are seconds.

    Pass rule, criterion by criterion (R4, the k of N reporting rule, is built into every line; R9 to R13 are information only).

    rule what has to hold 10,000 vertices 100,000 vertices
    R1, R2 record count of every type after import equals the source database (and the content digest of every property, non-null and null counts: R2) held (36 of 36) held (36 of 36)
    R3 types, property names and declared types, and index definitions equal after import held (36 of 36) held (36 of 36)
    R5 the source database equals the generator (a loader problem is not blamed on export or import) held (36 of 36) held (36 of 36)
    R6 the restored BACKUP DATABASE archive equals the source (counts and content) held (36 of 36) held (36 of 36)
    R7 negative control, one record deleted, caught as exactly one difference in the count held (12 of 12) held (12 of 12)
    R7 negative control, one p_long changed, caught as exactly one difference in that property held (12 of 12) did not hold (0 of 12)
    R8 3 repetitions per cell, source databases of the repetitions have identical digests held (12 of 12) held (12 of 12)
    R14 valid runs: no exception outside the timed call, no missing phase (every export and import call returned) held (108 of 108 export and import rows ok) held (108 of 108 export and import rows ok)
    R15 identity: every row is wheel 26.11.1.post2, one engine string per wheel, backend loaded held held
    R16 probe: each awkward value alone in a one-record database held (54 of 54) held (54 of 54)

    Round trip exact, per comparison (each comparison is one repetition of one cell; the fin and mix cells are both in these counts):

    vertices wheel R1 to R3 import = source R3 schema R5 source = generator R6 restore = source R7 controls (prop, cnt) R16 probe
    10,000 native 18 of 18 18 of 18 18 of 18 18 of 18 prop 6 of 6, cnt 6 of 6 27 of 27
    10,000 jvm 18 of 18 18 of 18 18 of 18 18 of 18 prop 6 of 6, cnt 6 of 6 27 of 27
    100,000 native 18 of 18 18 of 18 18 of 18 18 of 18 prop 0 of 6, cnt 6 of 6 27 of 27
    100,000 jvm 18 of 18 18 of 18 18 of 18 18 of 18 prop 0 of 6, cnt 6 of 6 27 of 27

    No export or import raised, and every probe case of the 27 per wheel (infinite and NaN floats, -0.0, the extremes of a 64-bit integer, DECIMAL scales, a NUL, unicode, nested list and map, a vector, the date types) round-trips exactly on both wheels, which agrees with ArcadeData/arcadedb#8871 being closed. No round trip failed, so this run files no upstream issue.

    Time, median (min to max) of 3 repetitions, mix cells:

    vertices cell records export native export JVM import native import JVM
    10,000 doc:mix 10,000 0.27 (0.26 to 0.27) 0.62 (0.60 to 0.62) 0.32 (0.32 to 0.32) 1.27 (1.26 to 1.32)
    10,000 graph:mix 60,000 0.47 (0.46 to 0.47) 1.08 (1.08 to 1.08) 1.05 (1.05 to 1.05) 2.59 (2.44 to 2.69)
    10,000 vec:mix 60,000 8.55 (8.55 to 8.59) 10.26 (10.26 to 10.31) 4.22 (4.20 to 4.24) 5.15 (5.06 to 5.24)
    100,000 doc:mix 100,000 2.50 (2.49 to 2.51) 2.81 (2.70 to 2.83) 3.06 (3.06 to 3.08) 3.73 (3.53 to 3.80)
    100,000 graph:mix 600,000 4.56 (4.55 to 4.56) 4.97 (4.88 to 5.00) 16.79 (16.70 to 16.90) 13.45 (13.39 to 13.55)
    100,000 vec:mix 600,000 87.25 (87.20 to 87.30) 97.54 (97.52 to 97.57) 53.03 (52.79 to 53.41) 33.95 (33.42 to 33.97)

    Seconds per million records (the median at that size scaled to a million, not measured at a million), and the time of the original load (insert_many for documents, graph_batch for the graph shapes, engine defaults, so its durability is not matched to import) and of BACKUP DATABASE, medians in seconds:

    vertices cell export s per M records native export JVM import native import JVM load (gen) s native load JVM backup s native backup JVM
    10,000 doc:mix 26.7 61.5 32.1 126.6 0.88 1.59 0.03 0.08
    10,000 graph:mix 7.8 17.9 17.5 43.1 0.81 2.44 0.07 0.11
    10,000 vec:mix 142.5 171.0 70.4 85.8 6.71 4.82 0.51 0.62
    100,000 doc:mix 25.0 28.1 30.6 37.3 8.87 9.97 0.17 0.23
    100,000 graph:mix 7.6 8.3 28.0 22.4 8.46 15.94 0.38 0.45
    100,000 vec:mix 145.4 162.6 88.4 56.6 69.01 35.95 4.84 5.51

    Peak resident memory, MiB, VmHWM right after the call, median (min to max); the last two columns are the same counter right after opening the database (the baseline of the interpreter and the native library or the JVM):

    vertices cell export peak MiB native export JVM import peak MiB native import JVM after open native after open JVM
    10,000 doc:mix 144 (144 to 144) 203 (200 to 238) 152 (152 to 152) 250 (234 to 274) 93 (92 to 93) 152 (146 to 155)
    10,000 graph:mix 150 (150 to 150) 260 (229 to 283) 174 (174 to 174) 334 (321 to 365) 93 (92 to 93) 150 (146 to 158)
    10,000 vec:mix 188 (187 to 188) 262 (258 to 269) 416 (416 to 419) 824 (793 to 944) 93 (92 to 93) 150 (147 to 153)
    100,000 doc:mix 161 (161 to 162) 324 (281 to 355) 170 (170 to 170) 430 (424 to 454) 88 (87 to 88) 151 (147 to 157)
    100,000 graph:mix 193 (193 to 194) 448 (395 to 486) 318 (317 to 318) 1109 (909 to 1203) 88 (88 to 89) 155 (150 to 158)
    100,000 vec:mix 560 (555 to 561) 864 (857 to 870) 1668 (1650 to 1718) 2414 (2412 to 2667) 88 (88 to 89) 154 (145 to 159)

    Disk, megabytes (10^6 bytes): the export file as written (.jsonl.tgz), the plain JSONL after decompressing it, and the BACKUP DATABASE archive:

    vertices cell export file MB native export file MB JVM plain JSONL MB native plain JSONL MB JVM plain / file native plain / file JVM backup zip MB native backup zip MB JVM
    10,000 doc:mix 1.16 1.14 5.16 4.07 4.44 3.57 1.20 1.19
    10,000 graph:mix 1.79 1.79 10.25 10.25 5.73 5.73 2.49 2.47
    10,000 vec:mix 38.36 38.35 95.94 95.94 2.50 2.50 31.51 31.48
    100,000 doc:mix 11.62 11.45 52.06 41.16 4.48 3.60 12.03 11.99
    100,000 graph:mix 18.48 18.47 105.01 105.00 5.68 5.69 25.76 25.72
    100,000 vec:mix 384.06 384.00 961.89 961.89 2.50 2.50 316.26 315.98
    The same four tables for the fin cells
    vertices cell records export native export JVM import native import JVM
    10,000 doc:fin 10,000 0.26 (0.26 to 0.26) 0.61 (0.54 to 0.62) 0.32 (0.32 to 0.32) 1.17 (1.16 to 1.25)
    10,000 graph:fin 60,000 0.46 (0.46 to 0.46) 1.09 (1.07 to 1.13) 1.06 (1.06 to 1.07) 2.58 (2.53 to 2.68)
    10,000 vec:fin 60,000 8.54 (8.54 to 8.55) 10.05 (9.99 to 10.26) 4.19 (4.17 to 4.21) 4.73 (4.60 to 5.17)
    100,000 doc:fin 100,000 2.50 (2.50 to 2.52) 2.85 (2.74 to 2.87) 3.09 (3.07 to 3.11) 3.47 (3.40 to 3.60)
    100,000 graph:fin 600,000 4.58 (4.56 to 4.59) 4.95 (4.88 to 4.95) 16.86 (16.79 to 16.97) 13.28 (13.15 to 13.35)
    100,000 vec:fin 600,000 87.33 (87.24 to 87.34) 97.69 (97.56 to 97.81) 53.15 (52.82 to 53.28) 33.76 (33.59 to 34.16)
    vertices cell export s per M records native export JVM import native import JVM load (gen) s native load JVM backup s native backup JVM
    10,000 doc:fin 26.3 61.0 31.9 117.0 0.91 1.67 0.03 0.09
    10,000 graph:fin 7.7 18.1 17.7 43.0 0.81 2.39 0.06 0.12
    10,000 vec:fin 142.3 167.5 69.8 78.9 6.67 4.71 0.50 0.62
    100,000 doc:fin 25.0 28.5 30.9 34.7 9.09 10.04 0.17 0.23
    100,000 graph:fin 7.6 8.2 28.1 22.1 8.51 15.95 0.38 0.45
    100,000 vec:fin 145.6 162.8 88.6 56.3 69.31 36.31 4.85 5.46
    vertices cell export peak MiB native export JVM import peak MiB native import JVM after open native after open JVM
    10,000 doc:fin 144 (144 to 144) 219 (207 to 227) 152 (152 to 152) 244 (239 to 260) 93 (92 to 93) 154 (149 to 159)
    10,000 graph:fin 150 (150 to 150) 272 (249 to 283) 176 (176 to 177) 309 (294 to 322) 93 (92 to 93) 152 (149 to 154)
    10,000 vec:fin 188 (188 to 188) 254 (252 to 259) 416 (416 to 419) 858 (721 to 940) 93 (92 to 93) 150 (149 to 152)
    100,000 doc:fin 161 (161 to 161) 335 (304 to 335) 170 (169 to 170) 428 (414 to 465) 88 (87 to 88) 155 (150 to 161)
    100,000 graph:fin 194 (193 to 194) 449 (430 to 471) 317 (315 to 318) 1006 (909 to 1165) 88 (87 to 89) 157 (152 to 159)
    100,000 vec:fin 560 (552 to 562) 868 (854 to 872) 1656 (1635 to 1724) 2553 (2450 to 2672) 88 (88 to 89) 156 (147 to 158)
    vertices cell export file MB native export file MB JVM plain JSONL MB native plain JSONL MB JVM plain / file native plain / file JVM backup zip MB native backup zip MB JVM
    10,000 doc:fin 1.16 1.14 5.16 4.04 4.45 3.56 1.20 1.19
    10,000 graph:fin 1.78 1.79 10.25 10.25 5.75 5.73 2.49 2.47
    10,000 vec:fin 38.35 38.35 95.94 95.94 2.50 2.50 31.51 31.48
    100,000 doc:fin 11.61 11.43 52.05 40.89 4.48 3.58 12.03 11.97
    100,000 graph:fin 18.47 18.46 105.00 105.00 5.69 5.69 25.77 25.73
    100,000 vec:fin 384.02 383.96 961.88 961.88 2.50 2.51 316.26 315.96

    Reading it. At 100,000 vertices on the native wheel, EXPORT DATABASE took 2.50 s for the documents, 4.56 s for the vertices with edges and 87.25 s with the vector column, and IMPORT DATABASE 3.06, 16.79 and 53.03 s. On the JVM wheel export took 2.81, 4.97 and 97.54 s and import 3.73, 13.45 and 33.95 s. In seconds per million records that is 25.0 (documents), 7.6 (vertices with edges) and 145.4 (vector) for export on native, and 30.6, 28.0 and 88.4 for import. The vector column is what costs: export of the vector cell is 19.1 times the export of the graph cell on native and 19.6 times on JVM, with 9.2 times the plain JSONL.

    Native or JVM wheel: at 10,000 vertices the JVM wheel was slower in every document and graph export and import, by 2.3x to 3.9x. At 100,000 vertices export on JVM took 1.08 to 1.14 times as long as on native, and import reversed for the two shapes with edges: 13.45 s on JVM against 16.79 s on native for vertices with edges, 33.95 against 53.03 s with the vector column, while documents stayed 1.2x slower on JVM. I did not test why; each phase is a fresh process, so the JVM wheel pays its warm-up in every call, which fits the gap at the small size and is a guess for the rest.

    The native import of the graph cell grew 16.0x for 10 times the vertices (the JVM wheel 5.2x). I looked at the stderr of every export and import phase at both sizes: engine INFO lines only (plus the JDK's incubator-module notice on the JVM wheel), no engine warning or error, and every phase exited 0. I did not find the reason, so I would not scale the 100,000 figures to a million.

    Memory at 100,000 vertices: export of the document cell peaked at 161 MiB (native) and 324 MiB (JVM), against 88 and 151 MiB right after opening; import of the vector cell peaked at 1,668 MiB (native) and 2,414 MiB (JVM, -Xmx4g). The JVM peak depends on the heap setting, the native wheel has no such setting here.

    Against the alternatives: EXPORT DATABASE took 11.1 to 18.0 times as long as BACKUP DATABASE of the same database (ratio of medians over the three shapes and both wheels), and import took 0.34, 1.98 and 0.77 of the original load time on native for documents, vertices with edges and the vector shape (JVM 0.37, 0.84, 0.94), so on native the import of the vertices with edges costs more than the load that built them. An Arrow load was not measured (it needs pyarrow, outside the wheel and the standard library).

    Disk: at 100,000 vertices the compressed export is 11.62 MB for documents (native-loaded records; 11.45 MB when the JVM wheel loaded them), 18.48 MB for vertices with edges and 384.06 MB with the vector (plain JSONL 52.06, 105.01 and 961.89 MB on native). The compressed graph and vector files of the two wheels differ by at most 0.3 percent. The documents again export to different text on the two wheels, as in the smoke: plain JSONL 52.06 MB from native-loaded records against 41.16 MB from JVM-loaded records (1.26x), and both round-trip exactly, so I read it as a stored-type difference between the two wheels' insert_many, which I have not traced.

    Against the smoke comment above: the 10,000-vertex medians of this run are 0.82 to 1.03 times the smoke's single repetition for export and import on both wheels (the smoke read 8.93 s native and 10.25 s JVM for the vector export, this run reads 8.55 and 10.26 s), and the plain JSONL sizes are byte for byte the same as in the smoke. The smoke ran the two wheels at the same time on the same four cores with the JVM wheel at -Xmx1g; this run took one wheel at a time at -Xmx2g. I think that explains the differences, which I did not test.

    Acceptance items. Harness, rules and the smoke: done earlier. Laptop run: done for 10,000 and 100,000 vertices, results above; the 1,000,000 cells have not run. Failed round trips become upstream issues: none failed, so none filed. Docs of the bindings: not written; I would put per-million figures in them only after a 1,000,000 run, given the native import scaling above.

    What the numbers do not say. One host (this laptop, on its low-power cores, so absolute times are slow ones), 3 repetitions per cell, 100,000 vertices at most, JDK 25 only, embedded mode only, a warm page cache, a clean close and no crash test, no server-mode export, engine defaults. The wheels' two families are never pooled.

    Edited 2026-11-12: the R3 row of the table above is wrong for the JVM wheel (the schema comparison was empty there). The correction is in #369 (comment).

  6. tae898 commented on Nov 11, 2026

    @tae898
    CollaboratorAuthor

    R7 holds at 50,000 vertices (24 of 24 negative controls caught as exactly 1 difference on both wheels, every R1 to R3, R5 and R6 comparison agrees at that size), and the 100,000-vertex verdict stays INVALID because the rule is unchanged.

    This is the control-only rerun I queued above. Method: 50,000 vertices, one repetition, the same seed (20261111) as the 100,000-vertex run, all six cells (documents, vertices with 5 edges each, and the same with a 768-dimension float32 vector, each in the mix and the fin variant) on both wheels (arcadedb==26.11.1.post2 and arcadedb-jvm==26.11.1.post2, engine build a3a5d12457, JDK 25.0.5 with max heap 4g), the same cores 12 to 15 under nice -n 19, and the same harness: the hashes of run.py, run_all.sh and score.py recorded by these runs equal the pinned ones of the earlier runs. At 50,000 vertices the harness keeps per-record hashes, so every difference is listed per record. I scored it as queued, score.py --reps 1, with no rule and no file edited. Both runs exited 0 in every phase, every row is ok, all six cells are present on each wheel, and the scorer says PASS (PASS=126, FAIL=0, INVALID=0, INCOMPLETE=0).

    Rule R7 applied literally: the control that adds 1 to one p_long (of p_id 3) was caught in 12 of 12 cells (6 per wheel) as exactly 1 difference in that property and in no other, for example Doc.p_long: 1 of 50000 e.g. 3; the control that deletes one record was caught in 12 of 12 cells as exactly 1 difference in the count of that type (Doc count: 1 of 50000 and Link count: 1 of 250000), with the properties of the deleted record differing by that one record. The other comparisons at this size: import equals source for counts, content digests, schema and indexes in 12 of 12 comparisons (R1 to R3), source equals generator in 12 of 12 (R5), the restored BACKUP DATABASE archive equals the source in 12 of 12 (R6), and the probe of single awkward values is exact in 54 of 54 cases (27 per wheel). No round trip failed.

    What it does not show. It does not change the 100,000-vertex verdict: R7 as pre-registered applies to that run, where the changed-value control could only be seen as a digest difference with the number of records unknown, so that run stays INVALID and I do not rescore it under another rule. What this run adds is the same harness, seed and code path at a size where the controls can be counted per record, and there they are caught exactly. It is one repetition per cell, so it has no spread and I do not use its times; the three-repetition tables above stand. It is the same host and the same two wheels, and 50,000 vertices is still not 1,000,000.

  7. tae898 commented on Nov 12, 2026

    @tae898
    CollaboratorAuthor

    A correction to my R3 row, which I got wrong for the JVM wheel.

    The R3 row of the table in my verdict comment says R3 (types, property names and declared types, and index definitions equal after import) held (36 of 36) at 10,000 and at 100,000 vertices. The 36 is 18 comparisons per wheel. On the native wheel those comparisons were real: all 18 of 18 at each size read a non-empty schema. On the JVM wheel they were not: at 10,000 vertices 18 of 18, at 100,000 vertices 18 of 18 (and 6 of 6 in the 50,000-vertex run) compared an empty description with an empty one. My schema reader kept only the nested rows that are Python dicts, and the JVM wheel hands the nested property and index rows of SELECT FROM schema:types over as Java objects, so every property and every index was dropped without an error and "equal" meant "both empty". Only the type names were compared there.

    What this does not touch: R1, R2, R5, R6 and the record controls of R7 (the changed p_long and the deleted record) compare content digests, and those were not empty on either wheel (12 to 17 digested properties in every digest file at 100,000 vertices, every p_id counted). The native schema comparison also had little to find, one index per main type (p_id) and no vector index, so even there the claim was narrow.

    So the R3 claim holds for the native wheel with that narrow schema and is not established for the JVM wheel. I have queued a corrected check as a separate folder. It reads the schema with three independent readers, refuses to pass unless a reader returns exactly the schema that was declared (so an empty comparison is INVALID, not a pass), uses a richer schema (an LSM_VECTOR index with cosine and 768 dimensions, a UNIQUE and two NOTUNIQUE indexes, an edge index, DECIMAL and DATETIME properties), and plants one difference in each of two copies of the source (an index dropped, a declared type changed) that has to be caught as exactly one difference on both wheels. It runs at 1,000, 10,000 and 100,000 vertices on both pinned wheels, and I will post the result here, whichever way it comes out. Sorry for the wrong claim.

  8. tae898 commented on Nov 12, 2026

    @tae898
    CollaboratorAuthor

    Result of the corrected schema check, as promised in my correction above: PASS at 10,000 and at 100,000 vertices on both wheels (arcadedb==26.11.1.post2 and arcadedb-jvm==26.11.1.post2, engine 26.11.1 build a3a5d12457). The scorer says PASS with 120 rules passed, 0 failed, 0 invalid and 0 incomplete.

    R3 (types, property names with declared types, and index definitions equal after import) compared 24 cell pairs and 24 passed. This time the comparison is not empty: the vector cells hold 2 types, 15 properties and 5 index definitions (an LSM_VECTOR cosine index on 768 dimensions, a UNIQUE and two NOTUNIQUE indexes, an edge index), the graph cells 2 types, 14 properties and 4 index definitions, and both wheels read the same schema. A cell only counts when its source database reads back exactly as declared, so an empty read would have been INVALID, not a pass.

    vertices wheel R3 cell pairs equal source read as declared planted differences caught
    10,000 native 6 of 6 6 12 of 12
    10,000 jvm 6 of 6 6 12 of 12
    100,000 native 6 of 6 6 12 of 12
    100,000 jvm 6 of 6 6 12 of 12

    Each planted difference (one index dropped, one declared type changed) was caught as exactly one difference, on both wheels. The 100,000-vertex content rules passed as well.

    Same limits as before: one repetition, one laptop, 100,000 vertices at most, and the schema was read through independent readers on each wheel. The first comment's timings and memory tables are unchanged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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