#28948: CookieStorage performance issues
--------------------------------------------+------------------------
               Reporter:  Michal Čihař      |          Owner:  nobody
                   Type:  Bug               |         Status:  new
              Component:  contrib.messages  |        Version:  2.0
               Severity:  Normal            |       Keywords:
           Triage Stage:  Unreviewed        |      Has patch:  0
    Needs documentation:  0                 |    Needs tests:  0
Patch needs improvement:  0                 |  Easy pickings:  0
                  UI/UX:  0                 |
--------------------------------------------+------------------------
 The CookieStorage tries to generate as big cookie as possible to fit all
 messages. However doing this on lot of small messages is very expensive
 and can take several seconds on the server, potentially leading to denial
 of service.

 Here is simple code to reproduce the slowness:


 {{{
 #!/usr/bin/env python

 # Configure needed settings
 from django.conf import settings
 settings.configure(MESSAGE_TAGS={})

 from django.contrib.sessions.middleware import SessionMiddleware
 from django.contrib.messages.middleware import MessageMiddleware
 from django.contrib.messages.storage.cookie import CookieStorage
 from django.contrib.messages.api import info
 from django.http.request import HttpRequest
 from django.http.response import HttpResponse
 from django.contrib.messages.storage import default_storage

 # Request and response objects
 response = HttpResponse()
 request = HttpRequest()

 # Process request by middleware
 SessionMiddleware().process_request(request)
 mm = MessageMiddleware()
 mm.process_request(request)

 # Insert messages
 for x in range(500):
     info(request, 'm:{0}'.format(x))

 # Measure response processing time
 import timeit
 print(timeit.timeit(
     'mm.process_response(request, response)',
     globals=globals(), number=10
 ))
 }}}

 In my case the DOS was triggered by broken client who repeatedly posted
 form generating message, but never did follow redirect to display the
 messages, so nothing really sophisticated.

 Quickly looking at the code following performance improvements come to my
 mind:

 * Avoid repeated encoding of the messages, encode them all at once and
 then operate on encoded strings
 * Avoid calculating HMAC while calculating length as length of it is fixed
 * Do bisect instead of removing messages one by one

-- 
Ticket URL: <https://code.djangoproject.com/ticket/28948>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/048.4d9ae8694f565948c74064fb710054c2%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to