You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 8ad0a21
Browse filesBrowse the repository at this point in the historyBrowse files
perf: cache per-class argument specs; make worker logging and profiling reachable
extract_argument_specs derives a function class's arguments from its
annotations, its FunctionArguments, and the Arg descriptors on its MRO —
none of which change once the class exists. It was nonetheless re-derived
on every catalog listing and every overload match.
Profiling one run of the upstream integration suite through the Cedar
proxy: 58,058 calls costing 15.8s, driving 131,653 typing.get_type_hints
calls, 2.4M _eval_type calls and 648k compile() calls — about a quarter of
the worker's CPU. catalog_schema_contents_functions cost 38ms per call
where every other catalog method was 0.1-2ms, entirely because of this.
After: 16.7ms per call, and 179x on the function itself in isolation.
Memoized with functools.cache, which is thread safe (workers serve on a
pool) and unbounded — the keys are function classes the catalog already
holds for the process's lifetime, so it retains nothing new. The cached
value is a tuple and the public function returns a fresh list, so a caller
that mutates the result cannot corrupt the cache; ArgumentSpec is a frozen
dataclass, so sharing the specs themselves is safe.
Two supporting changes, both about reaching diagnostics from outside:
VGI_WORKER_LOG_LEVEL / _FORMAT / _LOGGERS, applied inside
configure_worker_logging rather than in one CLI. The vgi_rpc.access log
already records duration_ms, method and row/byte counts for every RPC, but
turning it on required --log-logger and --log-format on the command line,
which anything launching a worker without owning its argv cannot do. Placed
in the shared function because vgi-serve and the fixture servers had
byte-identical logging blocks and wiring it into one would be a trap.
vgi/profiling.py: VGI_WORKER_PROFILE=<dir> writes pstats on exit. It uses a
single profiler deliberately — under --http the worker runs on waitress, so
a main-thread-only profile would show time in select() and nothing else,
and since Python 3.12 cProfile is sys.monitoring-based and process-global,
so one profiler covers the pool threads. A profiler per thread raises
"Another profiling tool is already active" as each waitress thread starts,
which stops the server accepting connections at all. SIGTERM is handled
because its default action skips interpreter shutdown, losing the profile
on every normal stop.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
0 commit comments