#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 django-updates+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/051.6f7db5385c1bf048babbeb8d698f2eb3%40djangoproject.com.

Reply via email to