Skip to content

Cache Session.gethookproxy during collection#6

Open
adamtheturtle wants to merge 5 commits into
mainfrom
adamtheturtle/faster-collect-gethookproxy
Open

Cache Session.gethookproxy during collection#6
adamtheturtle wants to merge 5 commits into
mainfrom
adamtheturtle/faster-collect-gethookproxy

Conversation

@adamtheturtle

@adamtheturtle adamtheturtle commented Jul 17, 2026

Copy link
Copy Markdown
Owner

Summary

Typing of gethookproxy / ihook as HookRelay | FSHookProxy is intentionally not in this PR; see pytest-dev/pytest#14728.

Background (pytest-dev#2016)

gethookproxy(path) returns either the full hook relay or an FSHookProxy that strips conftests that do not apply to that path. An earlier path→proxy cache was removed in #2073 because it caused pytest-dev#2016:

Given siblings demo-0, demo-a (with pytest_ignore_collect → True), and demo-b:

  1. Collecting root cached a “complete” proxy before any local conftest existed.
  2. Entering demo-a loaded its conftest onto that same cached complete proxy.
  3. Later collection under root reused the poisoned proxy, so demo-a’s ignore hook incorrectly affected siblings like demo-b.

The 2016 fix was to drop caching entirely and recompute every call. This PR restores caching for large-suite performance (pytest-dev#8991), but only with invalidation that covers that failure mode:

Guard What it covers
Clear when len(_conftest_plugins) grows Classic pytest-dev#2016: a newly imported conftest must not remain invisible (or wrongly global) on a cached proxy
Cache only if the directory is in _dirpath2confmods Sibling case: path looked up before conftests are associated for that directory; association later does not grow _conftest_plugins, so generation alone would not clear a stale FSHookProxy

Timing

Warm interleaved A/B pytest --collect-only -q (alternate order). +% = faster.

Home Assistant (tests/, 122 476 tests, 3 pairs)

Median
main 41.20s
This change 35.41s
Delta +5.79s (+14.1%)

vws-python-mock (1 403 tests, 10 pairs)

Median
main 0.315s
This change 0.375s
Delta −0.060s (−19.0%)

On HA, gethookproxy runs ~233k times across ~8k unique paths, so cache hits dominate. On vws-python-mock (~2k calls / ~130 paths, ~0.2s collect) absolute savings are tiny and the measured delta is within run-to-run noise.

pytest’s own testing/ suite (~4k tests, 12 pairs)

Within noise (main 0.535s → 0.540s, −0.9%).

Test plan

adamtheturtle and others added 2 commits July 17, 2026 15:41
Cache path-sensitive hook proxies and invalidate when conftests load. Do not
cache before a directory is recorded in _dirpath2confmods, which previously
could permanently strip root conftests from Package collection (pytest-dev#2016/pytest-dev#8991).

Co-authored-by: Cursor <cursoragent@cursor.com>
Keep comments focused on current invalidation rules; leave pytest-dev#2016 context
for the PR description.

Co-authored-by: Cursor <cursoragent@cursor.com>
adamtheturtle and others added 3 commits July 19, 2026 10:03
Return-type / ihook annotation cleanup lives in a separate PR.

Co-authored-by: Cursor <cursoragent@cursor.com>
Describe current invariants only; leave past context to the PR description.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant