You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
#[pyfunction] gets METH_STATIC since 0.28, which makes calls slower on CPython 3.11+ #6426
Since PyO3 0.28, every module-level #[pyfunction] is created with the METH_STATIC flag. A function with one parameter has ml_flags0xa2 (METH_FASTCALL | METH_KEYWORDS | METH_STATIC). With PyO3 0.27.2 it has 0x82.
The flag has two effects:
function.__self__ is None. With 0.27.2 it is the module, as it is for CPython's own builtin functions such as math.sqrt.
On CPython 3.11 and newer, a call of a function that has parameters and no **kwargs is about 2 to 4 ns slower. For a function with an empty body this is 10 to 21%. Functions without parameters and functions with **kwargs are not slower. CPython 3.9 and 3.10 are not affected.
I found this while benchmarking fastcrc after upgrading PyO3 from 0.26 to 0.29.2.
Steps to Reproduce
A reproduction is at https://github.com/overcat/pyo3-meth-static-repro. It defines pairs of functions with empty bodies. One function of each pair is a plain #[pyfunction]. The other one uses pass_module, which does not get the flag, and is the control.
With PyO3 0.27.2, both columns show the same flags, __self__ is the module in both, and the differences are 0.0 ns.
Your operating system and version
Linux Mint 22.3 (kernel 7.0.0-31-generic, x86-64)
Your Python version (python --version)
Python 3.14.6
Your Rust version (rustc --version)
rustc 1.98.0 (88d9e12ae 2026-08-18)
Your PyO3 version
0.29.2 (also 0.28.2 and main at cb456da; 0.27.2 is not affected)
How did you install python? Did you use a virtualenv?
mise (a precompiled python-build-standalone build), in a virtualenv created with "python -m venv"
Additional Info
This was introduced by #5581. The README of the reproduction explains the cause in PyO3 and in CPython. It also has the results for several PyO3 and CPython versions, the instruction counts and a workaround.
There is a candidate fix with a test: overcat@b3d1fd3. If you agree with the approach, I can turn it into a PR.
Yes. I am still preparing a reproduction script and the CPython issue. When they are ready, I will link them here.
I think PyO3 should still fix this on its side: a CPython fix will only land in future releases, and the flag also changed __self__ from the module to None. The two fixes do not conflict. If you agree, I can open the PR from overcat/pyo3@b3d1fd3.
Yes. I am still preparing a reproduction script and the CPython issue. When they are ready, I will link them here.
I think PyO3 should still fix this on its side: a CPython fix will only land in future releases, and the flag also changed __self__ from the module to None. The two fixes do not conflict. If you agree, I can open the PR from overcat/pyo3@b3d1fd3.
Great! A fix on both sides is perfect. Please open a PR.
I haven't included them in #6428 because these new benchmarks have no baseline on main for CodSpeed to compare against. If this looks useful, I can open a separate PR for the benchmarks so they can land first. Once main has recorded a baseline, we can rerun #6428 to see the difference in its CI report.
Activity
bschoenmaeckers commentedon Sep 17, 2026
Have you looked into fixing this in CPython?
ngoldbaum commentedon Sep 17, 2026
Seems like a straightforward fix to me. Would be nice to get benchmarks sensitive to this if we don't have any already.
overcat commentedon Sep 18, 2026
Yes. I am still preparing a reproduction script and the CPython issue. When they are ready, I will link them here.
I think PyO3 should still fix this on its side: a CPython fix will only land in future releases, and the flag also changed
__self__from the module toNone. The two fixes do not conflict. If you agree, I can open the PR from overcat/pyo3@b3d1fd3.bschoenmaeckers commentedon Sep 18, 2026
Great! A fix on both sides is perfect. Please open a PR.
overcat commentedon Sep 19, 2026
Hi @ngoldbaum I've prepared benchmarks in overcat@241ead4
I haven't included them in #6428 because these new benchmarks have no baseline on main for CodSpeed to compare against. If this looks useful, I can open a separate PR for the benchmarks so they can land first. Once main has recorded a baseline, we can rerun #6428 to see the difference in its CI report.
ngoldbaum commentedon Sep 21, 2026
Seems reasonable to me, go ahead.
overcat commentedon Sep 28, 2026
Just sharing for anyone interested: there's also a fix being worked on in CPython: python/cpython#157834