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.
* status: new => closed
* resolution: => invalid
* component: Uncategorized => HTTP handling
* type: Uncategorized => Cleanup/optimization
Comment:
Thanks for this proposition, however I don't think it's worth changing. I
don't see a significant improvement in Python 3.8:
{{{
.....................
Current: Mean +- std dev: 29.4 us +- 1.9 us
.....................
Option One: Mean +- std dev: 28.9 us +- 0.7 us
.....................
Option Two: Mean +- std dev: 28.9 us +- 0.7 us
.....................
Option Three: Mean +- std dev: 29.2 us +- 1.5 us
}}}
and in Python 3.10 is even worse:
{{{
.....................
Current: Mean +- std dev: 34.4 us +- 1.2 us
.....................
Option One: Mean +- std dev: 34.2 us +- 0.9 us
.....................
Option Two: Mean +- std dev: 34.7 us +- 0.9 us
.....................
Option Three: Mean +- std dev: 34.8 us +- 0.9 us
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/32945#comment:1>