Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Morsel.__init__ loops reserved values and could be replaced with a simple dict update #126156

Closed
bdraco opened this issue Oct 30, 2024 · 1 comment
Labels
performance Performance or resource usage stdlib Python modules in the Lib dir type-feature A feature request or enhancement

Comments

@bdraco
Copy link
Contributor

bdraco commented Oct 30, 2024

for key in self._reserved:

Backstory:
aio-libs/aiohttp#9594
Processing cookies is a significant part of the aiohttp request time, and some requesters have to create many Morsel objects because they have a lot of cookies on every request.

There are few places that can be optimized in http.cookies

This one is low hanging fruit

Linked PRs

bdraco added a commit to bdraco/cpython that referenced this issue Oct 30, 2024
Replaces the manually constructed loop with a call to `dict.update`
@bdraco
Copy link
Contributor Author

bdraco commented Oct 30, 2024

(venv) bdraco cpython % python3 morsel_bench.py
0.33160758309531957 - original
0.28600058297161013 - new
(venv) bdraco cpython % cat morsel_bench.py

from http.cookies import Morsel
import timeit


class FastMorsel(dict):
    """A class to hold ONE (key, value) pair.

    In a cookie, each such pair may have several attributes, so this class is
    used to keep the attributes associated with the appropriate key,value pair.
    This class also includes a coded_value attribute, which is used to hold
    the network representation of the value.
    """

    # RFC 2109 lists these attributes as reserved:
    #   path       comment         domain
    #   max-age    secure      version
    #
    # For historical reasons, these attributes are also reserved:
    #   expires
    #
    # This is an extension from Microsoft:
    #   httponly
    #
    # This dictionary provides a mapping from the lowercase
    # variant on the left to the appropriate traditional
    # formatting on the right.
    _reserved = {
        "expires": "expires",
        "path": "Path",
        "comment": "Comment",
        "domain": "Domain",
        "max-age": "Max-Age",
        "secure": "Secure",
        "httponly": "HttpOnly",
        "version": "Version",
        "samesite": "SameSite",
    }

    _reserved_defaults = {key: "" for key in _reserved}

    _flags = {"secure", "httponly"}

    def __init__(self):
        # Set defaults
        self._key = self._value = self._coded_value = None

        # Set default attributes
        dict.update(self, self._reserved_defaults)


print(timeit.timeit("Morsel()", globals={"Morsel": Morsel}))
print(timeit.timeit("FastMorsel()", globals={"FastMorsel": FastMorsel}))

@picnixz picnixz added type-feature A feature request or enhancement performance Performance or resource usage stdlib Python modules in the Lib dir labels Oct 30, 2024
hauntsaninja pushed a commit that referenced this issue Oct 31, 2024
Replaces the manually constructed loop with a call to `dict.update`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
performance Performance or resource usage stdlib Python modules in the Lib dir type-feature A feature request or enhancement
Projects
None yet
Development

No branches or pull requests

3 participants