Repository navigation
Conversation
|
CI on head 3403dd2: workflow_dispatch run 41716185993 of test-jvm.yml, 18 of 18 jobs succeeded, including all 10 test legs (the new tests/test_reader_crossings.py ran on each). No timed run exists yet; the PR stays draft. The timed A/B is prepared with its rule and the GRAY rerun clause written before any run. |
|
Timed A/B of this PR on the JVM wheel (laptop timed lane,
Clean pairs per figure: 12. By the rule written before the run (every gating upper end below 0.90, every control median inside [0.95, 1.05], a clean A/A) this is a SHIP. The control times a pure-Python This is the third run. The first two were invalid by the same rule and report nothing: their control was The PR leaves draft at the end of the current batch of timed studies that pin main, with its docs, and merges on green. I can re-run the study on the branch after any change. |
…et iteration in one crossing each (#227) Document.to_dict took 18 reads of Java objects for 3 properties, Result.to_dict 14, a property-names call 12, and each row of a result set two calls (hasNext, next). The new bridge class ReaderCalls writes a record or a row as the typed JSON of TypedRows (one call, one string read, the C json decoder), returns the names as one JSON text, and hands over the next row in one call. Values keep the types convert_java_to_python gives them; the side array is read only when the JSON refers to it; a result set is still read one row per call. Without the class the old paths run. Document.to_dict now also refreshes the cached names, so a property set after an earlier read is no longer missing from get_property_names(). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lt iteration) The study that adopts this PR timed record to dict at 3 and 12 properties and iteration into dicts at 100 and 10,000 rows on the arcadedb-jvm package. The Results section gets those four gating figures with their 95% intervals, the unit (time per record or row), the control that the change does not touch, and the scope (JVM build, these workloads, one laptop). The numbers are generated from the study's ab-score.md by script. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7cacef9 to
64efea3
Compare
Closes #227
The JVM build read a record, a row, a list of property names and each row of a result set through many JPype calls:
Document.to_dict()took 18 reads of Java objects for 3 properties,Result.to_dict()14, the property names 12, andfor row in rstwo calls per row (counts of an untimed census, see the issue; no timing yet). A new bridge class,ReaderCalls(src/java/com/arcadedb/python/ReaderCalls.java, compiled with the other bridge classes into the same jar), cuts each to one call:Result.to_dict()(results.py) andDocument.to_dict()(graph.py):ReaderCalls.rowJson/documentJsonwrite the row or record as the typed JSON ofTypedRows(the transportResultSet.to_list()already uses). Python makes one call, reads one array element and one string, and parses with the Cjsonmodule; the side array of the engine's own objects is read only when the JSON carries the tag character. Values have the typesconvert_java_to_pythongives them, and the key order is the engine's.get_property_names()andproperty_namesof both classes (_property_names_tuple):rowNames/documentNamesreturn the names as one JSON text instead of one JPype read per name.ResultSet.__next__(results.py):nextOrNulldoeshasNext()andnext()in one call. A row is still read when it is asked for, an error in the statement surfaces from the call as before, the end is the sameNoneashasNext()false, and the closed and exhausted states are unchanged.Without the class (a jar that lacks it) every caller takes the old path. The native build is not touched.
TypedRows.appendRowandTypedRows.quoteloseprivateso the new class can use them.One difference on purpose:
Document.to_dict()now stores the names of the read it just made, so a property set after an earlierto_dict()orget_property_names()is no longer missing from the nextto_dict()(the cached tuple of names was never refreshed on a mutable record). A record whose wrapped Java object is not acom.arcadedb.database.Document(a binary record) now raises aTypeErrorfrom the bridge call where it raisedAttributeErrorfor the missinggetPropertyNames.Tests (
tests/test_reader_crossings.py, JVM only, listed inNATIVE_NOT_APPLICABLE): a counting proxy on the bridge classes and the Java objects, which also counts the reads of the arrays and the Java set they return, pins the exact calls (to_dictis the call and one array read; the old path is at least 7 for a record and 9 for a row; iteration is one call per row against two), and every value type of the wide table, the values SQL cannot produce, tag-named properties and unusual property names are compared with an independent per-property read of the Java object (same Python types, same key order). Closed-database errors, laziness of iteration and the close semantics are pinned too.Overlap with #214 (issue #213): #214 edits
RowAccess.java,DbCalls.java,results.py(ResultSet.one,ResultSet.count),graph.py(Document.get_raw) andcore.py. This PR adds its Java in a new file, editsResultSet.__next__,Result._property_names_tuple,Result.to_dict,Document._property_names_tupleandDocument.to_dict, and one line oftests/conftest.py(next to the line #214 adds). The hunks do not touch, so the two merge in either order; the only shared line region is theNATIVE_NOT_APPLICABLEtable intests/conftest.py, which may need a trivial rebase.Status: the pre-registered timed A/B of the main CI JVM wheel against this PR's CI JVM wheel shipped by its rule. Figures and scope are in this comment and in the docs passage this PR now adds.
Docs: the Results section of
how-to/databases-and-queries.adochas the four timed figures (Document.to_dictat 3 and 12 properties, iterating a result into dicts at 100 and 10,000 rows) with their 95% intervals and the control, added in 7cacef9.🤖 Generated with Claude Code
Edited 2026-11-05: the status line now gives the timed result; the PR is ready for review.