Skip to content

Cache sniffio availability instead of importing it on every call - #1132

Merged
Kludex merged 2 commits into
pydantic:mainfrom
mbeijen:fix/sniffio-hot-path-import
Aug 13, 2026
Merged

Cache sniffio availability instead of importing it on every call#1132
Kludex merged 2 commits into
pydantic:mainfrom
mbeijen:fix/sniffio-hot-path-import

Conversation

@mbeijen

@mbeijen mbeijen commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

current_async_library() re-imported sniffio on every invocation, falling back to "asyncio" on ImportError. Since anyio>=4.11 no longer depends on sniffio, anyone using httpcore2[asyncio] without trio installed pays a failed-import cost on every lock/event/semaphore setup, and Python doesn't cache failed imports.

Now sniffio is imported once at module load, like trio and anyio already are, and current_async_library() just checks the cached reference. Only availability is cached, not the detected backend.

Reported in encode/httpcore discussion #1102, with the fix and test strategy suggested in a follow-up comment:
encode/httpcore#1102 (comment)

Summary

improve import time when modern anyio =->4.11 is installed and sniffio isn't

Checklist

  • I understand that this PR may be closed in case there was no previous discussion. (This doesn't apply to typos!)
  • I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change.

Review in cubic

@codspeed-hq

codspeed-hq Bot commented Aug 11, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 17 untouched benchmarks
⏩ 7 skipped benchmarks1


Comparing mbeijen:fix/sniffio-hot-path-import (b3f847f) with main (d03f1ec)

Open in CodSpeed

Footnotes

  1. 7 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

Re-trigger cubic

`current_async_library()` re-imported `sniffio` on every invocation,
falling back to "asyncio" on `ImportError`. Since anyio>=4.11 no
longer depends on sniffio, anyone using `httpcore2[asyncio]` without
trio installed pays a failed-import cost on every lock/event/semaphore
setup, and Python doesn't cache failed imports.

Now `sniffio` is imported once at module load, like `trio` and
`anyio` already are, and `current_async_library()` just checks the
cached reference. Only availability is cached, not the detected
backend.

Reported in encode/httpcore discussion pydantic#1102, with the fix and test
strategy suggested in a follow-up comment:
encode/httpcore#1102 (comment)
@mbeijen
mbeijen force-pushed the fix/sniffio-hot-path-import branch from 713688c to 03405e7 Compare August 11, 2026 12:32
@Kludex
Kludex enabled auto-merge (squash) August 13, 2026 12:34
@Kludex
Kludex merged commit 6f38ddf into pydantic:main Aug 13, 2026
16 checks passed
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.

2 participants