Skip to content

v0.36.0 — performance

Choose a tag to compare

@rustyconover rustyconover released this 18 Sep 21:09
· 178 commits to main since this release

Performance release.

Client: fan-out connections open when they get work

Client.scalar_function and table_in_out_function opened every connection max_workers allowed before sending the first batch. Scalar and table-in-out functions default to unlimited max_workers, so the client capped it at the CPU count: one call on one batch opened 48 connections on a 48-core machine — 47 idle worker processes on the subprocess transport. A secondary connection now opens when the first batch is dealt to it (batch i still goes to connection i % max_workers), so n batches use min(n, max_workers) connections. A trivial call went from 0.4–1 s to ~10 ms. table_function is unchanged (no input to deal).

Dynamic filters over HTTP: no more quadratic replay

HTTP table streams carried every dynamic-filter delta ever received in their per-turn state and replayed all of them — re-validating each predicate through the embedded DuckDB — on every turn, so turn k did k validations. The state now keeps only the deltas that set a predicate's current revision, and a turn rebuilt from state the worker sealed itself skips the re-check. With the matching extension change (it now sends a delta only when a filter changes), dynamic_filter.test went from ~205 s to ~8 s and sequence.test from ~109 s to ~8 s. The embedded filter evaluator runs single-threaded (it was a 48-thread pool per server thread).

Catalog listings built once

Every function listing rebuilt and Arrow-encoded a FunctionInfo for all of a worker's functions (≈134 ms of worker time per call for the example worker's 162 table functions). Each (schema, type) listing is now built once per worker and each item encoded once: a warm listing costs ≈0.3 ms. DuckDB makes this call when it loads a function set.

Smaller

  • vgi.auth loads its HTTP/JWT helpers on first use: import vgi 0.89 s → 0.56 s. vgi.auth.__all__ no longer lists them — import them by name, as before.
  • Test fixtures: partitioned fixtures declare max_workers equal to their work items; the suite runs with one OpenBLAS thread per process and xdist worksteal.

The vgi-python suite: 66–69 s → 15–27 s on 48 cores.