fix: bound TypeAdapter lru_cache to prevent memory leak in multi-threaded usage#2907
fix: bound TypeAdapter lru_cache to prevent memory leak in multi-threaded usage#2907giulio-leone wants to merge 1 commit intoopenai:mainfrom
Conversation
|
Friendly ping — CI is green and this is ready for review. Happy to address any feedback. Thanks! |
29a5d5a to
ae5c65b
Compare
|
Intervention note for this PR: Current blocker appears to be missing CI execution rather than failing jobs:
Suggested unblock sequence:
If useful, I can run a follow-up status sweep as soon as checks are attached. |
|
Friendly follow-up — this fixes a memory leak in multi-threaded usage where TypeAdapter's unbounded lru_cache grows indefinitely (#2672). The fix adds a bounded maxsize. Would appreciate a review. 🙏 |
|
This PR is ready for review — all CI checks pass, no merge conflicts, and all review threads have been resolved. Ready to merge when approved. 🚀 |
ae5c65b to
decc32f
Compare
|
Hi! 👋 Gentle ping — this PR is rebased, CI passes, and ready for review. Happy to address any feedback. Thanks! |
|
Hi! Gentle ping — this PR is rebased, CI passes, and ready for review. Happy to address any feedback. Thanks! |
Summary
Fixes #2672
Problem
_CachedTypeAdapteruseslru_cache(maxsize=None)(unbounded), which causes memory leak in multi-threaded environments. Whenresponses.parseis called from multiple threads, generic types likeParsedResponseOutputMessage[MyClass]are created anew by pydantic in each thread, generating distinct cache keys. This means the cache never hits and grows without bound.Root Cause
In
src/openai/_models.pyline 802:Python's
typingmodule creates new generic type objects in different threads, soParsedResponseOutputMessage[Fact]in thread A has a different identity thanParsedResponseOutputMessage[Fact]in thread B. Sincelru_cachekeys on object identity, each thread creates a new cache entry.Fix
Set
maxsize=4096to cap memory usage while still providing effective caching for typical workloads. This is a standard practice forlru_cache— the LRU eviction policy ensures the most-used types stay cached while preventing unbounded growth.Testing
Verified that the cache is bounded: