Repository navigation
Conversation
…tuple input (draft, ships only if the A/B passes) A decorator on NativeDatabase.insert_many, the native counterpart of the JVM change in #236 (#235): for a list or a tuple the collector is paused for the call and restored in finally (re-enabled only if it was enabled on entry); a generator or any other lazy input is not paused. The decorator leaves the body, the docstring and the signature of insert_many untouched so the change does not overlap the lines that #218 and #232 edit. Tests mirror the JVM ones. Draft: the native build's untimed probes found no collection inside the call, so this ships only if the timed A/B of DECISIONS #240 passes (Closes #237 when it does). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… keeps its own __defaults__) The decorator replaced insert_many with a (*args, **kwargs) function, so tests/test_native_columnar_insert.py, which patches insert_many.__defaults__, failed in setup (None is not subscriptable) and patching the wrapper would not have reached the real function. The pause is now six lines at the top of the body: for a list or tuple with the collector on, disable it, re-enter insert_many once (the collector is off, so the body runs) and enable again in finally; a lazy input or a collector the caller already disabled goes straight to the body. Signature, defaults and docstring are unchanged; a test asserts the defaults and that nothing wraps it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Head moved to |
…calls it (as the JVM change in #236), no re-entry through the public method Re-entering self.insert_many made an instance-level spy or a subclass override run twice per call. insert_many keeps its signature, __defaults__ and docstring, checks the database is open, pauses the collector for a list or tuple (restoring in finally), and passes commit_every explicitly to the body, so the columnar fixture's patched default still reaches it. A test asserts that a spy on insert_many sees one call for a list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Head moved to |
|
Test runs on head
The six that fail on main are the pause tests: |
|
Timed A/B on head
Clean pairs per figure: 11, 12. By the rule written before the run this is GRAY, no effect: the insert and load intervals lie inside the equivalence band [0.97, 1.03]. The study also counted the cyclic collections that run inside Speed was the only motive, so by the rule this PR does not ship. Closing it, and its issue, with this result; the tests that check the collector is restored after a call stay in this branch if the question comes back. |
Closes #237
DRAFT, and it ships only if its A/B passes. On the
arcadedb(native) build,insert_manywould pause Python's cyclic garbage collector for the duration of a call whenrowsis a list or a tuple, and restore the previous state infinally(re-enabled only if it was enabled on entry). A generator, an iterator, a DataFrame or any other lazy input is not paused. This is the native counterpart of the JVM change in #236 (issue #235), with the same guard and the same semantics.Why a separate decision: the JVM change was measured on the JVM build only (insert wall 0.819 to 0.903 of the default, 95% CI, #236). The untimed probe behind it found 19% to 28% of the JVM
insert_manywall in the collector and zero collections inside the nativeinsert_many, so the expected gain on native is nothing. That is a prediction from single untimed runs on earlier wheels, so the timed A/B on the current main wheel decides: arm A is the native CI wheel of main, arm B is the same wheel with only_native/database.pyfrom this PR's head, arm Z is A again, 1,000,000 rows in slices of 100,000,ab.py --noise, with a control load whose caller has already disabled the collector. The rule (the thresholds of the JVM study), the round plan and the policy for a GRAY result are fixed in the study README before the first timed run. If the A/B does not pass, this PR is closed unmerged with the measurements on issue #237 and the native default stays.Code: 14 added lines in
NativeDatabase.insert_many(src/arcadedb/_native/database.py), the same structure as the JVM change in #236.insert_manykeeps its signature,__defaults__and docstring, checks that the database is open, and for a list or tuple while the collector is on callsgc.disable(), runs the body and callsgc.enable()infinally. The body is moved unchanged into a private_insert_many_nogc(self, type_name, rows, commit_every, parallel), which a lazy input, or a collector the caller already disabled, reaches directly, so nothing is restored that this call did not disable.insert_manydoes not call itself, so a spy or a subclass override of it sees one call per call, and it passescommit_everyexplicitly, so the patched default oftests/test_native_columnar_insert.pystill reaches the body. Two earlier heads are withdrawn:cedf3a8(a decorator, which broke that test because it patchesinsert_many.__defaults__) and3b2eaaa(re-entry through the public method). Tests:tests/test_native_insert_many_gc_pause.py(native only, ignored on the JVM build inconftest.py) observesgc.isenabled()from inside the call for a list and a tuple, several chunks, the parallel mode, an exception, a collector the caller had disabled, a generator, an iterator and a generator expression, rows given by keyword, and a call without rows, asserts thatinsert_many.__defaults__is(1000, False)and that nothing wraps it, and that an instance-level spy oninsert_manysees exactly one call for a list.Overlap with other open PRs on
NativeDatabase.insert_many: #218 (headab207e667e) changes the imports, the docstring and the body ofinsert_many; #232 (headf91cf142aa) changes one docstring line of it. This PR adds 14 lines:import gcat the top of the file, the block after_check_not_closed()and a newdef _insert_many_nogc(line above the unchanged body, so it changes neither the body, the docstring nor the signature.git merge-treeof this branch with the heads of #218, #232 and #236 reports no conflict for each pair. #236 (JVM) editscore.py,tests/conftest.py(a line inNATIVE_NOT_APPLICABLE) and the bulk-loads page; this PR adds a line in a different part ofconftest.py.Docs: none yet, on purpose. TODO if the A/B passes: extend the bulk-loads section that #236 adds so that it covers the native build (today it says the native package does not change the collector), and add the same sentence to the
insert_manydocs; if it does not pass, no docs change and the sentence in #236 stays true.Static checks run on head
3bc5f63:compile()of the three files, pyflakes (only the three existingnumpyandpyarrowunused-import notes, none on a line of this change), black 26.10.1 and isort 9.0.2 unchanged. The tests run in CI (Test native, dispatched on the branch because the pull_request run skips a draft).Edited 2026-11-04: the code paragraph and the overlap paragraph now describe head
3bc5f63(body in_insert_many_nogc); they described the withdrawn headscedf3a8and3b2eaaabefore.🤖 Generated with Claude Code