Skip to content

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

Closed

Description

@bdraco

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

Activity

  1. added a commit that references this issue on Oct 30, 2024
  2. bdraco commented on Oct 30, 2024

    @bdraco
    ContributorAuthor

    (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}))
  3. added
    type-featureA feature request or enhancement
    performancePerformance or resource usage
    stdlibStandard Library Python modules in the Lib/ directory
    on Oct 30, 2024
  4. added a commit that references this issue on Oct 31, 2024
  5. added a commit that references this issue on Dec 8, 2024
  6. added a commit that references this issue on Jan 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    performancePerformance or resource usagestdlibStandard Library Python modules in the Lib/ directorytype-featureA feature request or enhancement

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions