-
-
Notifications
You must be signed in to change notification settings - Fork 625
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
Memory growth fast when schema is defined in a function #657
Comments
For two reasons:
Note that because of reference counting in CPython (I'm making an assumption on your environment here), this doesn't result in double memory for a single registry entry. tl;dr your infinite loop causes infinite registry entries which uses infinite memory. And despite the registry, this might happen anyways due to module-class relationships. |
Hey @justanr, thanks for the reasoning and details explanation here which I appreciate. I too have hit this issue which causes high memory issues in my production environment. Now that I am aware of it I would like to know the suggested solution, in what I see as a valid use case here. I typically use inheritance to generate classes to give standard packaging.
This way I can easily standardize my response formats across my schemas.
Is there a suggested solution here. I was thinking about manually checking things in spots, but I fear its hard to train others users to follow suit and avoid the memory leaks. |
@jtillman You can prevent marshmallow from storing your generated classes in its internal registry of schemas by generating the classes without a name. class ResponseObject(Schema):
@classmethod
def load_paged_result(cls, data):
fields = {
'page_number': fields.Integer(),
'total': fields.Integer(),
'items': fields.List(fields.Nested(cls)),
}
attrs = dict(fields, Meta=Meta)
# Create a nameless class to prevent storing the class in
# marshmallow's in-memory registry
ResponsePageObject = type(str(''), (ma.Schema,), attrs)
return ResponsePageObject(strict=True).loads(data)
class UserResponse(ResponseObject):
name = fields.String() I've also proposed #660 , which would expose a more straightforward way to bypass the registry. In the meantime, the above workaround should get you most of the way. |
Thanks for the workaround. In thinking about this, it feels like a global registry should be something that people have to opt into rather than out of. Simply because its a feature that you have to dig for to know about and basic use of the library that generate schemas, can lead to huge memory issues that are a pain to pinpoint (which was the case for me). |
Let's follow the discussion in #660. |
When I use the following code, I observe that memory growth is very fast, but when I define the schema outside the function, there is no problem.
The text was updated successfully, but these errors were encountered: