fix: performance regression when sniffio not installed - #1103
Open
CedricCabessa wants to merge 1 commit into
Open
fix: performance regression when sniffio not installed#1103CedricCabessa wants to merge 1 commit into
CedricCabessa wants to merge 1 commit into
Conversation
`sniffio` is optional and lazily imported in `current_async_library`, when absent we use `asyncio` However the cost of import failure is paid every time the function is called. This patch moves the import at module level, like it is already done for `anyio` or `trio` Why it happens now?: Httpcore never explicitly declared `sniffio` but it was installed via `anyio` until they stopped depending on it: agronholm/anyio#1021 Here is a sample to reproduce the issue ``` import asyncio import time import httpcore REQUESTS = 500 RESPONSE = b"HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nok" async def handle(reader, writer): try: while await reader.readuntil(b"\r\n\r\n"): writer.write(RESPONSE) await writer.drain() except (asyncio.IncompleteReadError, ConnectionResetError): pass writer.close() async def main(): try: import sniffio # noqa: F401 status = "INSTALLED" except ImportError: status = "ABSENT" server = await asyncio.start_server(handle, "127.0.0.1", 0) url = f"http://127.0.0.1:{server.sockets[0].getsockname()[1]}/" async with httpcore.AsyncConnectionPool() as pool: await pool.request("GET", url) # warm up the pool cpu = time.process_time() for _ in range(REQUESTS): await pool.request("GET", url) cpu = time.process_time() - cpu print(f"sniffio {status}: {cpu / REQUESTS * 1e6:.0f} us CPU per request") server.close() asyncio.run(main()) ``` On my machine: | httpcore | sniffio | CPU / req | |----------|-----------|-----------| | master | installed | ~330 µs | | master | missing | ~500 µs | | patched | missing | ~330 µs | | patched | installed | ~330 µs |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
discussion: #1102
sniffiois optional and lazily imported incurrent_async_library, when absent we useasyncioHowever the cost of import failure is paid every time the function is called.
This patch moves the import at module level, like it is already done for
anyioortrioWhy it happens now?:
Httpcore never explicitly declared
sniffiobut it was installed viaanyiountil they stopped depending on it:agronholm/anyio#1021
Here is a sample to reproduce the issue
On my machine: