Performance of attribute lookup for type objects

eendebakpt · GitHub

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:

The benchmark is from the python side, but we are working with the C-API

The performance is important for numpy, see

PERF: Improve performance of special attribute lookups numpy/numpy#21423

Another location where this is a bottleneck:

https://github.com/python/cpython/blob/v3.12.0a2/Lib/dataclasses.py#L1301

Your environment

CPython versions tested on: Python 3.11.0a7+

Operating system and architecture: Linux Ubuntu

Linked PRs

gh-92216: improve performance of hasattr for type objects #99977

gh-92216: improve performance of hasattr for type objects #99979