#36520: Performance Regression in parse_header_params
-----------------------------+-----------------------------------------
     Reporter:  David Smith  |                     Type:  Uncategorized
       Status:  new          |                Component:  HTTP handling
      Version:  5.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
-----------------------------+-----------------------------------------
 https://github.com/django/django/pull/18424  / #35440 simplified the
 `parse_header_params()` function.

 This introduced a performance regression than can be seen on django-asv.
 [https://django.github.io/django-asv/regressions.xml link] shows 5
 performance regressions on or arround 28 March 2025, all of which relate
 to this commit.

 A minimal reproduction shows a 5x performance regression.

 Before:

 {{{
 In [2]: %timeit parse_header_parameters("text/plain")
 500 ns ± 1.42 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops
 each)
 }}}

 After
 {{{
 In [2]: %timeit parse_header_parameters("text/plain")
 2.65 μs ± 44.7 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops
 each)
 }}}

 Running a [https://pypi.org/project/line-profiler/#quick-start-modern
 line-profile] shows:

 {{{
 Line #      Hits         Time  Per Hit   % Time  Line Contents
 ==============================================================
    320                                           @line_profiler.profile
    321                                           def
 parse_header_parameters(line, max_length=MAX_HEADER_LENGTH):
    322                                               """
    323                                               Parse a Content-type
 like header.
    324                                               Return the main
 content-type and a dictionary of options.
    325
    326                                               If `line` is longer
 than `max_length`, `ValueError` is raised.
    327                                               """
    328         1         11.0     11.0      2.4      if max_length is not
 None and line and len(line) > max_length:
    329                                                   raise
 ValueError("Unable to parse header parameters (value too long).")
    330
    331         1         47.0     47.0     10.3      m = Message()
    332         1         51.0     51.0     11.2      m["content-type"] =
 line
    333         1        332.0    332.0     73.0      params =
 m.get_params()
    334
    335         1          2.0      2.0      0.4      pdict = {}
    336         1          7.0      7.0      1.5      key =
 params.pop(0)[0].lower()
    337         1          2.0      2.0      0.4      for name, value in
 params:
    338                                                   if not name:
    339                                                       continue
    340                                                   if
 isinstance(value, tuple):
    341                                                       value =
 collapse_rfc2231_value(value)
    342                                                   pdict[name] =
 value
    343         1          3.0      3.0      0.7      return key, pdict
 }}}

 As I think this function is called with every request, I thought it worth
 raising.
-- 
Ticket URL: <https://code.djangoproject.com/ticket/36520>
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 visit 
https://groups.google.com/d/msgid/django-updates/01070198345276d8-02273378-aaca-4507-99d2-de930e447b66-000000%40eu-central-1.amazonses.com.

Reply via email to