Skip to content
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

Merged
merged 13 commits into from
Jun 3, 2023
Merged
23 changes: 19 additions & 4 deletions fastapi/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,18 @@
import warnings
from dataclasses import is_dataclass
from enum import Enum
from typing import TYPE_CHECKING, Any, Dict, Optional, Set, Type, Union, cast
from typing import (
TYPE_CHECKING,
Any,
Dict,
MutableMapping,
Optional,
Set,
Type,
Union,
cast,
)
from weakref import WeakKeyDictionary

import fastapi
from fastapi.datastructures import DefaultPlaceholder, DefaultType
Expand Down Expand Up @@ -98,11 +109,15 @@ def create_response_field(
def create_cloned_field(
field: ModelField,
*,
cloned_types: Optional[Dict[Type[BaseModel], Type[BaseModel]]] = None,
cloned_types: Optional[
MutableMapping[Type[BaseModel], Type[BaseModel]]
] = WeakKeyDictionary(),
zanieb marked this conversation as resolved.
Show resolved Hide resolved
) -> ModelField:
# _cloned_types has already cloned types, to support recursive models
# cloned_types caches already cloned types to support recursive models and improve
# performance by avoiding unecessary cloning
if cloned_types is None:
cloned_types = {}
cloned_types = WeakKeyDictionary()

original_type = field.type_
if is_dataclass(original_type) and hasattr(original_type, "__pydantic_model__"):
original_type = original_type.__pydantic_model__
Expand Down