#32945: Improve performance of HttpRequest._current_scheme_host()
-----------------------------------------+------------------------
               Reporter:  David Smith    |          Owner:  nobody
                   Type:  Uncategorized  |         Status:  new
              Component:  Uncategorized  |        Version:  3.2
               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              |
-----------------------------------------+------------------------
 `_current_scheme_host()` currently uses `.format`. I propose that we
 change this to an `f-string` for a c.7.5% performance gain.

 There's a few different ways this could be written, I think OptionTwo
 would be the one which would meet Django's f-string guidelines. I've shown
 a few different versions to show that moving to f-string is the big win
 here and adding a few extra variables (or not) as no impact.

 One thing to note is that this function is decorated with
 `cached_property` but I've removed this to benchmark the underlying
 function.


 {{{
 .....................
 Current: Mean +- std dev: 243 us +- 4 us
 .....................
 Option One: Mean +- std dev: 226 us +- 2 us
 .....................
 Option Two: Mean +- std dev: 225 us +- 3 us
 .....................
 Option Three: Mean +- std dev: 226 us +- 2 us
 }}}

 {{{
 import pyperf
 from django.conf import settings
 from django.http import HttpRequest
 import django


 settings.configure(ALLOWED_HOSTS = ['localhost'])
 django.setup()

 class CurrentHttpRequest(HttpRequest):
     def _current_scheme_host(self):
         return '{}://{}'.format(self.scheme, self.get_host())

 class OptionOneHttpRequest(HttpRequest):
     def _current_scheme_host(self):
         return f'{self.scheme}://{self.get_host()}'

 class OptionTwoHttpRequest(HttpRequest):
     def _current_scheme_host(self):
         host = self.get_host()
         return f'{self.scheme}://{host}'

 class OptionThreeHttpRequest(HttpRequest):
     def _current_scheme_host(self):
         scheme = self.scheme
         host = self.get_host()
         return f'{scheme}://{host}'

 def current(loops):
     request = CurrentHttpRequest()
     request.META['SERVER_NAME'] = 'localhost'
     request.META['SERVER_PORT'] = '80'
     range_it = range(loops)
     t0 = pyperf.perf_counter()

     for loop in range_it:
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()

     return pyperf.perf_counter() - t0

 def option_one(loops):
     request = OptionOneHttpRequest()
     request.META['SERVER_NAME'] = 'localhost'
     request.META['SERVER_PORT'] = '80'
     range_it = range(loops)
     t0 = pyperf.perf_counter()

     for loop in range_it:
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()

     return pyperf.perf_counter() - t0

 def option_two(loops):
     request = OptionTwoHttpRequest()
     request.META['SERVER_NAME'] = 'localhost'
     request.META['SERVER_PORT'] = '80'
     range_it = range(loops)
     t0 = pyperf.perf_counter()

     for loop in range_it:
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()

     return pyperf.perf_counter() - t0

 def option_three(loops):
     request = OptionThreeHttpRequest()
     request.META['SERVER_NAME'] = 'localhost'
     request.META['SERVER_PORT'] = '80'
     range_it = range(loops)
     t0 = pyperf.perf_counter()

     for loop in range_it:
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()
         request._current_scheme_host()

     return pyperf.perf_counter() - t0

 runner = pyperf.Runner()
 runner.bench_time_func('Current', current)
 runner.bench_time_func('Option One', option_one)
 runner.bench_time_func('Option Two', option_two)
 runner.bench_time_func('Option Three', option_three)

 }}}

-- 
Ticket URL: <https://code.djangoproject.com/ticket/32945>
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 view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/051.6f7db5385c1bf048babbeb8d698f2eb3%40djangoproject.com.

Reply via email to