Cache RefResolver subschemas lookup per instance - #4590
Conversation
_get_subschemas_cache() re-ran a full breadth-first walk of the entire schema document (_search_schema) on every resolve() call, despite its name. The referrer schema is immutable for a resolver instance, so memoize the result. Removes the top self-time hotspot on large templates. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Additional measurement in a CI environment, since Apple-Silicon numbers proved unreliable for small effects elsewhere: same-runner interleaved 3-way A/B/C (ubuntu-latest; 72 real-world templates, ~250–340 KB each; one full-set
Every pass of this branch is faster than every baseline pass: ~4.5% end-to-end on this workload — somewhat below the ~7% single-template number in the description, but cleanly separated from noise (the wheel arm's own spread was 0.3%). |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4590 +/- ##
=======================================
Coverage 94.42% 94.42%
=======================================
Files 429 429
Lines 15099 15103 +4
Branches 2916 2917 +1
=======================================
+ Hits 14257 14261 +4
Misses 461 461
Partials 381 381
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Issue #, if available: none — follow-up to #4586, found while profiling for #4585
Description of changes:
RefResolver._get_subschemas_cache()re-ran a full breadth-first walk of the entire referrer schema document (_search_schema) on everyresolve()call, despite the name suggesting a cache. The referrer schema is immutable for the lifetime of a resolver instance, so memoize the result on the instance (a newinit=Falsefield).Benchmarks (v1.53.2 baseline): on a ~330 KB real-world template, cumulative profile time in
_get_subschemas_cachedrops 1.65s → 0.05s (the top self-time hotspot remaining after #4586); end-to-end wall clock on that template goes 4.20s → 3.90s (Apple M-series, best of 6, ~−7%). On a CI runner, a same-runner interleaved 3-way comparison over 72 real-world templates measured ~−4.5% end-to-end with zero overlap between arms — full table in the comment below.Full unit test suite passes (2644 passed, 1 skipped); ruff, ruff-format, isort, and mypy are clean on the changed file.
Prepared with AI assistance (Claude Code).
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.