Steps to reproduce
Lets say we have model like this:
class User(models.Model):
first_name = models.CharField()
last_name = models.CharField()
and serializer like this:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('first_name', 'last_name')
and whenever we serialize python obj, the data property has reference to serializer:
serializer = UserSerializer(instance=User.objects.first())
serializer.data.serializer is serializer # gives true
It works fine on small objects like in the example, but it starts consuming more memory with larger querysets and nested Serializers, just because of that data.serializer reference. Python reference counter cannot delete the data.serializer object, because data property references on that, and such a way we have to wait until GC collects it.
The data.serializer reference is only used (at least it is single usage I found) in HTMLFormRenderer and it looks like overhead. Also I'm pretty sure there are lots of projects the do not use the renderer at all, but have to "suffer" from that extra memory usage.
If I change our serializer like below, it consumes less memory:
class UserSerializer(serializers.ModelSerializer):
@property
def data(self):
ret = super(Serializer, self).data
#return ReturnDict(ret, serializer=self) <----original code
return ReturnDict(ret)
So, my point is to make the serializer reference optional, depending if HTMLFormRenderer is used or not, or pass it via renderer context.
class GenericAPIView(views.APIView):
def get_serializer_context(self):
context = super().get_serializer_context()
context['needs_serializer_ref'] = HTMLFormRenderer in self.renderer_classes
return context
and then in serializer do:
class Serializer(BaseSerializer):
@property
def data(self):
ret = super(Serializer, self).data
if self.context.get('needs_serializer_ref'):
return ReturnDict(ret, serializer=self)
return ret
Just an idea.
Thoughts ?
PS.
Ready to submit a PR
Steps to reproduce
Lets say we have model like this:
and serializer like this:
and whenever we serialize python obj, the
dataproperty has reference to serializer:It works fine on small objects like in the example, but it starts consuming more memory with larger querysets and nested Serializers, just because of that
data.serializerreference. Python reference counter cannot delete thedata.serializerobject, becausedataproperty references on that, and such a way we have to wait until GC collects it.The
data.serializerreference is only used (at least it is single usage I found) in HTMLFormRenderer and it looks like overhead. Also I'm pretty sure there are lots of projects the do not use the renderer at all, but have to "suffer" from that extra memory usage.If I change our serializer like below, it consumes less memory:
So, my point is to make the
serializerreference optional, depending ifHTMLFormRendereris used or not, or pass it via renderer context.and then in serializer do:
Just an idea.
Thoughts ?
PS.
Ready to submit a PR