* chore: update add-django-cprofile-filter.patch * fix: only use "draft" state when making aliases * refactor: eliminate repeated get_state_slug() On dev, reduces time for a draft-aliases api call by by 10-15% * refactor: only annotate inactive drafts * refactor: de-lint * refactor: speed up get_draft_authors_emails Another 20% or so improvement in response time * fix: guard against null person
82 lines
3.4 KiB
Diff
82 lines
3.4 KiB
Diff
--- django_cprofile_middleware/middleware.py.old 2024-06-27 21:03:56.975128007 +0000
|
|
+++ django_cprofile_middleware/middleware.py 2024-06-27 23:45:59.421683008 +0000
|
|
@@ -19,6 +19,16 @@
|
|
from django_cprofile_middleware.utils import MiddlewareMixin
|
|
|
|
|
|
+class Stats(pstats.Stats):
|
|
+ def filter_stats(self, regex):
|
|
+ oldstats = self.stats
|
|
+ self.stats = newstats = {}
|
|
+ filter = re.compile(regex)
|
|
+ for func, (cc, nc, tt, ct, callers) in oldstats.iteritems():
|
|
+ if filter.search(pstats.func_std_string(func)):
|
|
+ newstats[func] = (cc, nc, tt, ct, callers)
|
|
+
|
|
+
|
|
class ProfilerMiddleware(MiddlewareMixin):
|
|
"""
|
|
Simple profile middleware to profile django views. To run it, add ?prof to
|
|
@@ -38,9 +48,11 @@
|
|
?download => Download profile file suitable for visualization. For example
|
|
in snakeviz or RunSnakeRun
|
|
|
|
- This is adapted from an example found here:
|
|
- http://www.slideshare.net/zeeg/django-con-high-performance-django-presentation.
|
|
+ Patched with https://github.com/omarish/django-cprofile-middleware/pull/23
|
|
+ for operation with Django 4.2.5+
|
|
"""
|
|
+ PROFILER_REQUEST_ATTR_NAME = '_django_cprofile_middleware_profiler'
|
|
+
|
|
def can(self, request):
|
|
requires_staff = getattr(
|
|
settings, "DJANGO_CPROFILE_MIDDLEWARE_REQUIRE_STAFF", True)
|
|
@@ -52,10 +64,11 @@
|
|
|
|
def process_view(self, request, callback, callback_args, callback_kwargs):
|
|
if self.can(request):
|
|
- self.profiler = profile.Profile()
|
|
+ profiler = profile.Profile()
|
|
+ setattr(request, self.PROFILER_REQUEST_ATTR_NAME, profiler)
|
|
args = (request,) + callback_args
|
|
try:
|
|
- return self.profiler.runcall(
|
|
+ return profiler.runcall(
|
|
callback, *args, **callback_kwargs)
|
|
except Exception:
|
|
# we want the process_exception middleware to fire
|
|
@@ -63,12 +76,13 @@
|
|
return
|
|
|
|
def process_response(self, request, response):
|
|
- if self.can(request):
|
|
- self.profiler.create_stats()
|
|
+ if hasattr(request, self.PROFILER_REQUEST_ATTR_NAME):
|
|
+ profiler = getattr(request, self.PROFILER_REQUEST_ATTR_NAME)
|
|
+ profiler.create_stats()
|
|
if 'download' in request.GET:
|
|
import marshal
|
|
|
|
- output = marshal.dumps(self.profiler.stats)
|
|
+ output = marshal.dumps(profiler.stats)
|
|
response = HttpResponse(
|
|
output, content_type='application/octet-stream')
|
|
response['Content-Disposition'] = 'attachment;' \
|
|
@@ -76,9 +90,14 @@
|
|
response['Content-Length'] = len(output)
|
|
else:
|
|
io = StringIO()
|
|
- stats = pstats.Stats(self.profiler, stream=io)
|
|
+ stats = Stats(profiler, stream=io)
|
|
|
|
- stats.strip_dirs().sort_stats(request.GET.get('sort', 'time'))
|
|
+ if request.GET.get('stripdirs', False):
|
|
+ stats = stats.strip_dirs()
|
|
+ filter = request.GET.get('filter', None)
|
|
+ if filter:
|
|
+ stats.filter_stats(filter)
|
|
+ stats.sort_stats(request.GET.get('psort') or 'time')
|
|
stats.print_stats(int(request.GET.get('count', 100)))
|
|
|
|
response = HttpResponse('<pre>%s</pre>' % io.getvalue())
|