Repository navigation
Conversation
Port of humemai/arcadedb-embedded-python#525 (closed when the bindings moved here) onto today's _native code. An untimed per-call decomposition on the laptop put about 15 of 34 us of `SELECT .. WHERE id = ? .first()` in Python outside the engine. What changes, behaviour identical: - codec.encode_params: one exact-int or exact-str parameter is written as '{"pos": [v]}' directly (the bytes json.dumps gives) without the set of types and the encoder call; bool, int/str subclasses, floats and everything else keep the general path. - lib.exec_query: arcadedb_n_exec for a text-only parameter list without the by-name getattr, the thread-handle call and the argument tuple; same reply reader as call_bin (a float32 tail still decodes). database._exec uses it, with cached language and statement bytes. - NativeResultSet.first(): when the first batch holds the row and the result is readable, take it and close, without the iterator protocol. Same state afterwards as the iterator path (closed, not marked drained). - Record wrap: the import in NativeResult._record and records._java_object is done once, and _wrap looks the class up in a module dict. Dropped from #525: the lookup_by_key statement cache (lookup_by_key now calls the engine's lookupByKey through arcadedb_n_lookup; it still gains from the first() change), and the shared Java-object stand-in per process (each record keeps its own, only the import is cached). Untimed numbers from the old study (us per call, whole call incl. two get() calls): SELECT .. WHERE id = ? .first() 34.36 -> 29.60; encode_params 2.39 -> 0.58, json_loads 4.86 -> 4.49 (unchanged by this, see the follow-up note on a binary first batch). These are a decomposition on the previous code, not a speed claim: the timed A/B on the current wheel is still to run. tests/test_native_point_read.py (native backend only, collected in conftest): the one-parameter text equals json.dumps and the general encoder for 13 int/str values and 17 other kinds, the point-read rows equal the iterator and to_list() rows (float32 tail, escapes, multi-byte text), first() state and errors, record wrapping per kind, lookup_by_key, and a spy that the short path is the one taken. The two spy tests fail on the previous code, the others pass on both. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Draft: the speed claim waits for the timed A/B on the current native wheel (queued on the laptop, results will be posted here). Only the behaviour is claimed now: results are identical to the long path.
Port of humemai/arcadedb-embedded-python#525 (closed when the bindings moved here), rewritten onto the current
_nativecode. A point read (db.query("sql", "SELECT FROM T WHERE id = ?", v).first()) spends about 15 of 34 us in Python outside the engine in an untimed per-call decomposition on the laptop, so the change shortens that Python part. No Java, no native-image rebuild: the wheel'slibarcadedb.sois the same.Changes:
codec.encode_params: one exactintor exactstrparameter is written as{"pos": [v]}directly (the bytesjson.dumpsgives), without the type-set check and the encoder call.bool, subclasses, floats and everything else take the general path as before.lib.exec_query:arcadedb_n_execfor a text-only parameter list, without the by-namegetattr, the thread-handle call and the argument tuple. It reads the reply ascall_bindoes (a float32 tail still decodes).NativeDatabase._execuses it with cached language and statement bytes (lib.bc).NativeResultSet.first(): when the first batch holds the row and the result is readable, take the row and close, without the iterator protocol. The state afterwards is the iterator path's (closed, not marked drained); a lazy command result, an empty result or a closed database take the old path.recordsimport inNativeResult._recordand thedatabaseimport inrecords._java_objectare done once, and_wrap/_wrap_dictlook the class up in a module dict.Dropped from #525 because current code already covers or changed it: the
lookup_by_keystatement cache (it now calls the engine'slookupByKeythrougharcadedb_n_lookup; it still gains from thefirst()change), and the shared Java-object stand-in (each record keeps its own object, only the import is cached, so identity andsetattrbehaviour do not change).Untimed numbers from the old study (us per call, whole call including two
get()calls):SELECT .. WHERE id = ? .first()34.36 to 29.60,encode_params2.39 to 0.58,json_loads4.86 to 4.49 (not touched here). These describe the previous code and are not a speed claim. The deciding timed figure will besql_by_id_first_us, withlookup_by_key_us,range_1000_rows_usandcypher_2hop_count_usas guards, A/B on the current wheel with an A/A control.Tests:
tests/test_native_point_read.py(native backend only, listed inconftest.py) pins the one-parameter text againstjson.dumpsand the general encoder for 13 int/str values and 17 other kinds, point-read rows against the iterator andto_list()(float32 tail, escapes, multi-byte text),first()state and errors, record wrapping per kind,lookup_by_key, and a spy that the short path is the one taken. Run against the unpacked26.11.1.dev0linux-x86_64 wheel with this PR's four Python files overlaid (they are byte-identical tomainin the wheel): new file 99 passed; with ittest_native_result_transport,test_resultset,test_parameter_binding,test_lookup_by_key_index,test_results_after_close,test_positional_count,test_record_id_values,test_graph_api,test_resultset_read_errors,test_typed_rows,test_percall_callsandtest_native_columnar_insertpassed (the skips are the suite's NA-JVM/NOTYET entries). The two spy tests fail on the unpatched wheel, the rest pass on both. black 26.10.1, isort 9.0.2--profile blackand bandit are clean.🤖 Generated with Claude Code