Skip to content

Instantly share code, notes, and snippets.

@xyb
Forked from tclancy/middleware.py
Last active August 23, 2023 05:32
Show Gist options
  • Save xyb/859b245651ab8c9965c595df7a15171d to your computer and use it in GitHub Desktop.
Save xyb/859b245651ab8c9965c595df7a15171d to your computer and use it in GitHub Desktop.
Django middleware for Pympler (compatible with Django 2.0+)
# Derived from Piotr Maliński's example with a few modifications to use logging and :
# http://www.rkblog.rk.edu.pl/w/p/profiling-django-object-size-and-memory-usage-pympler/
import logging
import os
from django.conf import settings
from pympler import muppy
from pympler.asizeof import asizeof
from pympler.muppy import summary
def print_diff(start_objects, end_objects, path, response_size):
sum_start = summary.summarize(start_objects)
sum_end = summary.summarize(end_objects)
diff = summary.get_diff(sum_start, sum_end)
log = logging.getLogger("memdiff")
log.info("Top 10 memory deltas after processing %s", path)
log.info("%-60s %10s %10s", "type", "# objects", "total size")
for row in sorted(diff, key=lambda i: i[2], reverse=True)[:10]:
log.info("%60s %10d %10d", *row)
start_size = asizeof(start_objects)
end_size = asizeof(end_objects)
log.info(
"Processed %s: memory delta %0.1f kB (%0.1f -> %0.1fMB), "
"response size: %0.1f kB",
path,
(end_size - start_size) / 1024.0,
start_size / 1048576.0,
end_size / 1048576.0,
response_size / 1024.0,
)
class MemoryMiddleware:
"""
Measure memory taken by requested view, and response
"""
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
if not (
os.getenv("MEMORY_DIFF")
or request.GET.get("memory_diff")
or request.POST.get("memory_diff")
or request.headers.get("memory_diff")
):
return self.get_response(request)
if self._is_static_request(request):
return self.get_response(request)
start_objects = muppy.get_objects()
response = self.get_response(request)
path = request.META["PATH_INFO"]
end_objects = muppy.get_objects()
print_diff(start_objects, end_objects, path, len(response.content))
return response
def _is_static_request(self, request):
path = request.META["PATH_INFO"]
return settings.STATIC_URL and settings.STATIC_URL in path
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment