Repository navigation
Python driver: lower latency under concurrent use — wanted upstream? #1135
zahariash
started this conversation in
Show and tell
Replies: 1 comment 4 replies
|
Have you tested with 3.15 + free threading? I'm thinking "defer" at this point to figure out how the no-GIL APIs stabilize (or not). |
4 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Hello!
Thanks for keeping this db alive and kicking :)
Goal. My use case is an asyncio service with mostly light 1–20 ms queries and some large exports to polars or occasional longer query. On
main, one export or one big parameterized compile stalls every other Python thread, including the event loop, because the driver holds the GIL there. I have changes that fix this and want to ask whether they are wanted upstream before opening PRs.The changes.
get_as_arrow()/get_as_pl().get_as_df()reads number, date and string columns.Connection(num_threads=...)means when several connections run queries at once.Results (main → branch, default settings; laptop with 16 logical CPUs, 5 rounds; cloud VM with 2 vCPUs, 3 rounds):
get_as_pl(), 200k × 4The export in the mix is slower (+12% on 16 cores, +32% on 2 vCPUs: 35.3 → 39.4 ms and 70.3 → 92.5 ms) because it no longer blocks the small queries; LDBC and the heavy queries are within noise. Method: LDBC SNB SF1 (the graph-benchmark-ldbc queries plus 7 heavy ones), synthetic graphs, and an async mix of 3 clients running small parameterized queries while 1 client repeatedly exports 100k rows to polars; interleaved rounds, medians.
Threads per query:
"auto"(work in progress, not proposed yet).AsyncConnection(max_threads_per_query="auto")sets each query's thread limit at start: the database's threads divided among the queries then running, at least 2, all when it starts alone. It replaces an earlier static even split, which slowed heavy queries running alone by 50–100%. The default stays 0."auto"Costs: 8 in flight on 4 connections, p95 +19%; 4 heavy in flight, p50 +11–20% at equal throughput. On 2 vCPUs (minimum 2) it behaves like the default; minimum 1 trades one-hop 4-in-flight +58% and mix p99 15.9 → 7.1 ms for LDBC 4-in-flight p95 +31%. Blocker: a cached parameterized plan keeps aggregate partitions sized by its first run's thread limit; a
count(DISTINCT)first run while others run is later 47% slower alone (30% on 2 vCPUs). Sizing them by the database's thread count is an engine change, so"auto"stays opt-in.Questions.
I wonder:
"auto"be wanted, and would that engine change be acceptable?No is a fine answer: a low-latency driver may matter only to me, and I can keep this in a fork.
All reactions