New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
⚡ Update create_cloned_field
to use a global cache and improve startup performance
#4645
Conversation
Does not close #4644 - see comment in the linked issue. |
Isn't this a similar solution as what has been proposed here? #4105 |
@orfisko Yeah it is! I missed that implementation since it wasn't linked to an issue. The choices here are a little different:
|
For others who read this, this comment refers specifically to an issue with using dynamically generated models with |
2b6ed83
to
4d7d18e
Compare
📝 Docs preview for commit 4d7d18e at: https://636aa2502be5da007c6dc54e--fastapi.netlify.app |
📝 Docs preview for commit d741490 at: https://636aa752e169f6006f8afab1--fastapi.netlify.app |
This is a great addition and sorely needed for the application I'm working on. Please let me know if there's anything I can do to help push this over the finish line! |
when is this going to merge and release? |
d741490
to
6ab34f2
Compare
Note that coverage is failing because this utility is not explicitly tested and consequently there's not coverage for actually using a custom @tiangolo The CI failures at https://github.com/tiangolo/fastapi/actions/runs/3535147825/jobs/5932836062 appear to be related to an change in GitHub actions that breaks Python when using |
📝 Docs preview for commit 6ab34f2 at: https://637e77005289633eb24dbfd5--fastapi.netlify.app |
📝 Docs preview for commit b64052f at: https://638366a8319a3972152f2ec9--fastapi.netlify.app |
📝 Docs preview for commit f378dfa at: https://63837048cb2392708ef8aca8--fastapi.netlify.app |
📝 Docs preview for commit 076f15a at: https://639ce7f5ecf1fd09839b403e--fastapi.netlify.app |
Is this ready to ship? Anything I can do to help push this across the finish line? |
This is ready to ship |
@tiangolo any chance we could get this merged, if it's ready to go? this is a huge win, making both app startup and test startup significantly faster. |
📝 Docs preview for commit bf5c338 at: https://63fcf8ba6775e90057a15a43--fastapi.netlify.app |
Indeed @tiangolo. This would be a nice win all around :) |
📝 Docs preview for commit d8bea1e at: https://643b6e9ed45d4c5bfe2bf01b--fastapi.netlify.app |
📝 Docs preview for commit ac82725 at: https://645507701034401069366570--fastapi.netlify.app |
@tiangolo What's required to get this merged? |
📝 Docs preview for commit 7184259 at: https://645ea712446d774207e234db--fastapi.netlify.app |
📝 Docs preview for commit 730717c at: https://646f7e9ccc99ff0466e10339--fastapi.netlify.app |
Hey team, looking forward for this merge :) |
create_cloned_field
to use a global cachecreate_cloned_field
to use a global cache and improve startup performance
Awesome, thanks a lot @madkinsz! 🙇 Thanks everyone for the comments, sorry for the long delay. 😅 🙈 I've been working on the migration to Pydantic v2, which will make this This will be available in FastAPI 0.96.0, released in the next hours. 🚀 @huonw I'm making you an honorary co-author of this PR for your work on #4105 that was before this. I'm taking this one just for the simplification in the changes/diff, the weakref, and keeping the signature. 🤓 |
Resolves issue reported in #4644 by instantiating a global dictionary to store cloned fields. This prevents repeated copying of models which can have significant performance affects. Please see the issue for more details.
This uses a
WeakKeyDictionary
so we avoid holding a reference to the model. I doubt this will have much practical affect since response model types are often globally defined, but it seems like good practice. This should not increase memory overhead since all the models generated bycreate_cloned_field
will be in scope for the scope of the FastAPI application anyway — users have noted this can significantly reduce memory consumption as it does not create as many model copies.It assigns the dictionary as a default value instead of moving the parameter to an explicitly global value. This allows a new cache to be passed if desired. However, mutable default values can be confusing and it would be fair to move it out of the function signature.edit: this change was made to meet test coverage.#4644 includes profiling indicating the performance increases here.
As mentioned in the issue, #894 (comment) refers to an alternative approach that would require work in Pydantic that would make this function irrelevant. That seems better in the long, but this is an easier patch for now.
See also discussion at #8609
Related to #4644