Opened 4 years ago
Closed 4 years ago
#32945 closed Cleanup/optimization (invalid)
Improve performance of HttpRequest._current_scheme_host()
| Reported by: | David Smith | Owned by: | nobody |
|---|---|---|---|
| Component: | HTTP handling | Version: | 3.2 |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
_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)
Change History (1)
comment:1 by , 4 years ago
| Component: | Uncategorized → HTTP handling |
|---|---|
| Resolution: | → invalid |
| Status: | new → closed |
| Type: | Uncategorized → Cleanup/optimization |
Thanks for this proposition, however I don't think it's worth changing. I don't see a significant improvement in Python 3.8:
and in Python 3.10 is even worse: