Skip to content

Instantly share code, notes, and snippets.

@ckkz-it
Last active November 28, 2022 13:06
Show Gist options
  • Save ckkz-it/941c4c7b3f03213e8c05cdaa87234e97 to your computer and use it in GitHub Desktop.
Save ckkz-it/941c4c7b3f03213e8c05cdaa87234e97 to your computer and use it in GitHub Desktop.
Django Rest Framework serializer benchmark for queries count and time estimation
class UserSerializer(serializers.ModelSerializer):
clients = serializers.ListField(source='client_names') # Model's property to retrieve `clients` names
sales = serializers.IntegerField(source='get_sales_overall_amount') # Model's method
address = serializers.CharField(source='address.street')
manager_name = serializers.CharField(source='manager.full_name')
@staticmethod
def setup_eager_loading(queryset):
""" Perform necessary eager loading of data. """
# select_related for "one-to-many" and "one-to-one" relationships (`ForeignKey`, `OneToOne`)
queryset = queryset.select_related(
'company',
'address',
'manager',
)
# prefetch_related for "many-to-many" relationships (`ManyToMany`)
queryset = queryset.prefetch_related(
'clients',
'sales',
)
return queryset
class Meta:
model = User
fields = ('id', 'first_name', 'last_name', 'email', 'phone', 'company', 'address', 'manager', 'clients', 'sales')
import os
import django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "app.name.settings")
django.setup()
from app.auth.models import User
from app.auth.serializers import UserSerializer
from app.utils.test_utils import benchmark_serialization
def user_serializer_bench(limit=1, should_print_data=False):
benchmark_serialization(
model=User,
serializer_class=UserSerializer,
limit=limit,
should_print_data=should_print_data,
)
if __name__ == '__main__':
user_serializer_bench(limit=10)
from contextlib import contextmanager
from pprint import pprint
from time import time
from django.db import reset_queries, connection
class colors(object):
end = '\033[0m'
black = '\033[1;30m'
red = '\033[1;31m'
green = '\033[1;32m'
def print_colored(data, color=colors.red, centered=False, print_empty_line=False):
if centered:
data = ' {} '.format(data).center(40, '-')
print('{color}{data}{end}{empty_line}'.format(
color=color,
data=data,
end=colors.end,
empty_line='\n' if print_empty_line else '',
))
def sql_bench(should_print_sql):
indentation = 2
width = 80
total_time = 0.0
if len(connection.queries) > 0:
print_colored('queries: {}'.format(len(connection.queries)))
for query in connection.queries:
total_time = total_time + float(query['time'])
if should_print_sql:
nice_sql = query['sql'].replace('"', '').replace(',', ', ')
sql = '{color}[{time}]{end} {sql}'.format(
color=colors.red,
time=query['time'],
end=colors.end,
sql=nice_sql,
)
while len(sql) > width - indentation:
print_colored("{ident}{sql}".format(
ident=" " * indentation,
sql=sql[:width - indentation]
))
sql = sql[width - indentation:]
print_colored(sql)
print_colored('time spent on queries: {time} seconds'.format(time=str(total_time)))
@contextmanager
def time_and_queries(name='Unnamed Timing'):
reset_queries()
print_colored(name, colors.green, centered=True)
start_time = time()
try:
yield
finally:
overall_time = time() - start_time
sql_bench(should_print_sql=False)
print_colored('time spent overall: {:.3f} seconds'.format(overall_time))
print_colored('END', centered=True, print_empty_line=True)
def benchmark_serialization(model, serializer_class, limit, should_print_data, with_eager_loading=False):
print_colored('Benchmark `{serializer_name}` with {limit} item{s}'.format(
serializer_name=serializer_class.__name__,
limit=limit,
s='s' if limit > 1 else '',
), colors.black, print_empty_line=True)
with time_and_queries('Without Eager Loading'):
qs = model.objects.all()[:limit]
serializer = serializer_class(qs, many=True)
data = serializer.data
if should_print_data:
pprint(data)
if with_eager_loading:
with time_and_queries('With Eager Loading'):
qs = model.objects.all()[:limit]
qs = serializer_class.setup_eager_loading(qs)
serializer = serializer_class(qs, many=True)
data = serializer.data
if should_print_data:
pprint(data)
@ckkz-it
Copy link
Author

ckkz-it commented Apr 4, 2020

Output example:
preview

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment