﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
36520	Performance Regression in parse_header_params	David Smith	Natalia Bidart	"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. "	Bug	closed	HTTP handling	dev	Release blocker	fixed		Carlton Gibson Jake Howard Mike Edmunds	Ready for checkin	1	0	0	0	0	0
