Skip to content

Performance of attribute lookup for type objects #92216

Description

@eendebakpt

Bug report

The performance of attribute lookup for type objects is worse than for other objects. A benchmark

import pyperf
runner=pyperf.Runner()

setup="""
class Class:
    def all(self):
        pass

x=Class()
"""

runner.timeit('hasattr x.all', "hasattr(x, 'all')", setup=setup)
runner.timeit('hasattr x.__array_ufunc__', "hasattr(x, '__array_ufunc__')", setup=setup)
runner.timeit('hasattr Class.all', "hasattr(Class, 'all')", setup=setup)
runner.timeit('hasattr Class.__array_ufunc__', "hasattr(Class, '__array_ufunc__')", setup=setup) # worse performance

Results:

hasattr x.all: Mean +- std dev: 68.1 ns +- 1.1 ns
hasattr x.__array_ufunc__: Mean +- std dev: 40.4 ns +- 0.3 ns
hasattr Class.all: Mean +- std dev: 38.1 ns +- 0.6 ns
hasattr Class.__array_ufunc__: Mean +- std dev: 255 ns +- 2 ns

The reason seems to be that the type_getattro always executes PyErr_Format, wheras for the "normal" attribute lookup this is avoided (see here and here)

Notes:

Your environment

  • CPython versions tested on: Python 3.11.0a7+
  • Operating system and architecture: Linux Ubuntu

Linked PRs

Activity

  1. seberg commented on May 3, 2022

    @seberg
    Contributor

    Related to this issue, I am wondering if we can consider _PyObject_LookupAttr either as stable (removing the _) or as "semi stable"?
    Of course that is only faster currently for the default tp_getattro, but I suspect that is a huge amount of calls.

    EDIT: Ah, I half thought it was not fully internal API right now, but "semi" exposed.

  2. eendebakpt commented on May 3, 2022

    @eendebakpt
    ContributorAuthor

    Also see: #76752 (PRs where _PyObject_LookupAttr is introduced)

  3. serhiy-storchaka commented on May 4, 2022

    @serhiy-storchaka
    Member

    _PyObject_LookupAttr is an internal API.

    I'll look if it is possible to speed up lookup of the absent attribute in a class object.

  4. added a commit that references this issue on Dec 23, 2022
  5. Fidget-Spinner commented on Dec 23, 2022

    @Fidget-Spinner
    Member

    @eendebakpt thanks for the improvement. Can I close this issue now or do you plan to submit more PRs?

  6. eendebakpt commented on Dec 23, 2022

    @eendebakpt
    ContributorAuthor

    The issue is solved, i will close

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

    3.12only security fixesperformancePerformance or resource usagetype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions