diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 0000000000..62033cb79d --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,4 @@ +Release type: patch + +This release improves the performance when returning a lot of data, especially +when using generic inputs (where we got a 7x speedup in our benchmark!). diff --git a/TWEET.md b/TWEET.md new file mode 100644 index 0000000000..45deaf0475 --- /dev/null +++ b/TWEET.md @@ -0,0 +1,6 @@ +🆕 Release $version is out! Thanks to $contributor for the PR 👏 + +This release improves the performance when returning a lot of data, especially +when using generic inputs (where we got a 7x speedup in our benchmark!). + +Get it here 👉 $release_url diff --git a/strawberry/annotation.py b/strawberry/annotation.py index c269ffd565..d39fe5a62a 100644 --- a/strawberry/annotation.py +++ b/strawberry/annotation.py @@ -54,7 +54,7 @@ class StrawberryAnnotation: - __slots__ = "raw_annotation", "namespace", "__eval_cache__" + __slots__ = "raw_annotation", "namespace", "__resolve_cache__" def __init__( self, @@ -65,7 +65,7 @@ def __init__( self.raw_annotation = annotation self.namespace = namespace - self.__eval_cache__: Optional[Type[Any]] = None + self.__resolve_cache__: Optional[Union[StrawberryType, type]] = None def __eq__(self, other: object) -> bool: if not isinstance(other, StrawberryAnnotation): @@ -101,19 +101,17 @@ def annotation(self) -> Union[object, str]: def annotation(self, value: Union[object, str]) -> None: self.raw_annotation = value + self.__resolve_cache__ = None + def evaluate(self) -> type: """Return evaluated annotation using `strawberry.util.typing.eval_type`.""" - evaled_type = self.__eval_cache__ - if evaled_type: - return evaled_type - annotation = self.raw_annotation + if isinstance(annotation, str): annotation = ForwardRef(annotation) evaled_type = eval_type(annotation, self.namespace, None) - self.__eval_cache__ = evaled_type return evaled_type def _get_type_with_args( @@ -131,6 +129,12 @@ def _get_type_with_args( def resolve(self) -> Union[StrawberryType, type]: """Return resolved (transformed) annotation.""" + if self.__resolve_cache__ is None: + self.__resolve_cache__ = self._resolve() + + return self.__resolve_cache__ + + def _resolve(self) -> Union[StrawberryType, type]: evaled_type = cast(Any, self.evaluate()) if is_private(evaled_type): @@ -172,7 +176,7 @@ def set_namespace_from_field(self, field: StrawberryField) -> None: module = sys.modules[field.origin.__module__] self.namespace = module.__dict__ - self.__eval_cache__ = None # Invalidate cache to allow re-evaluation + self.__resolve_cache__ = None # Invalidate cache to allow re-evaluation def create_concrete_type(self, evaled_type: type) -> type: if has_object_definition(evaled_type): diff --git a/strawberry/arguments.py b/strawberry/arguments.py index c73df9a9bc..ee32fe36f8 100644 --- a/strawberry/arguments.py +++ b/strawberry/arguments.py @@ -129,7 +129,6 @@ def type(self) -> Union[StrawberryType, type]: @property def is_graphql_generic(self) -> bool: - # TODO: double check this from strawberry.schema.compat import is_graphql_generic return is_graphql_generic(self.type)