Where: src/params.rs:108-134 (header_get_lax), called for authorization, cookie, content-type, origin, and the rate-limit key header — several times per request.
The function tries up to 3 case variants (name, lowercase, uppercase) against a PyDict downcast, then falls back to up to 3 getattr("get").call1(...) attempts, allocating a new lowercase/uppercase String each time. Granian's RSGI headers are already lowercase per spec, so in the common case this does far more work (and allocation) than a single lookup needs.
Fix direction: try the exact/lowercase name once; only fall back to case-insensitive scanning if that misses, and avoid allocating both a lowercase and uppercase copy up front.
Where:
src/params.rs:108-134(header_get_lax), called for authorization, cookie, content-type, origin, and the rate-limit key header — several times per request.The function tries up to 3 case variants (
name, lowercase, uppercase) against aPyDictdowncast, then falls back to up to 3getattr("get").call1(...)attempts, allocating a new lowercase/uppercaseStringeach time. Granian's RSGI headers are already lowercase per spec, so in the common case this does far more work (and allocation) than a single lookup needs.Fix direction: try the exact/lowercase name once; only fall back to case-insensitive scanning if that misses, and avoid allocating both a lowercase and uppercase copy up front.