Repository navigation
Commit d80869a
release: 0.23.0 — cached argument specs, reachable worker diagnostics
Ships 8ad0a21, which has been on main and green in CI but unreleased.
extract_argument_specs derives a function class's arguments from data that
cannot change once the class exists — its annotations, its
FunctionArguments, and the Arg descriptors on its MRO — but was re-deriving
them on every catalog listing and every overload match. Profiling a run of
the upstream integration suite through the Cedar proxy found 58,058 calls
costing 15.8s, driving 131,653 typing.get_type_hints calls, 2.4M _eval_type
calls and 648k compile() calls: roughly a quarter of the worker's CPU.
catalog_schema_contents_functions was 38ms per call where every other
catalog method was 0.1-2ms, entirely because of this. Measured on the same
41,733-RPC workload after: 16.7ms. In isolation the function itself is 179x
faster.
Memoized with functools.cache — thread safe, which matters because workers
serve on a pool, and unbounded because the keys are function classes the
catalog already holds for the process lifetime, so it retains nothing that
was not already retained. The cached value is a tuple and the public
function returns a fresh list, so a caller mutating the result cannot
corrupt the cache; ArgumentSpec is frozen, so sharing the specs is safe.
Also makes two diagnostics reachable from outside the process, which is how
the profiling above was possible at all:
VGI_WORKER_LOG_LEVEL / _FORMAT / _LOGGERS, applied inside
configure_worker_logging rather than in one CLI. The vgi_rpc.access log
already recorded duration_ms, method and row/byte counts per RPC, but
reaching it needed --log-logger and --log-format on the command line, which
anything launching a worker without owning its argv cannot supply. Placed in
the shared function because vgi-serve and the fixture servers had identical
logging blocks and wiring it into one would be a trap.
vgi/profiling.py: VGI_WORKER_PROFILE=<dir> writes pstats on exit. 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>1 parent 8ad0a21 commit d80869a
2 files changed
Lines changed: 2 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| |||
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
0 commit comments