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
[C API] Support the limited C API in debug mode (Py_INCREF and Py_DECREF) #87854
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee=Noneclosed_at=<Date2021-05-26.22:20:07.057>created_at=<Date2021-04-01.06:47:31.015>labels= ['expert-C-API', '3.10']
title='[C API] Support the limited C API in debug mode (Py_INCREF and Py_DECREF)'updated_at=<Date2021-05-26.22:20:07.056>user='https://github.com/vstinner'
Currently, setup.py doesn't build xxlimited and xxlimited_35 extension modules with the limited C API if Python is built in debug mode. I only found two functions affected by Py_DEBUG macro in the limited C API: Py_INCREF() and Py_DECREF().
If Py_DEBUG is defined (Python built in debug mode), Py_INCREF() increments the private _Py_RefTotal variable.
The limited C API is supposed to provide a stable ABI, but Py_INCREF() leaks _Py_RefTotal implementation if Python is built in debug mode.
I propose to modify Py_INCREF() and Py_DECREF() of the limited C API to always declare them as opaque function calls. The regular (non limited) C API will continue to use the same static inline functions.
See also #25115 and bpo-41111 "[C API] Convert a few stdlib extensions to the limited C API (PEP-384)".
Note: Py_XINCREF() and Py_XDECREF() should be fine.
changed the title [-][C API] Fix Py_INCREF and Py_DECREF in the limited C API for Python built in debug mode[/-][+][C API] Support the limited C API in debug build (Py_INCREF and Py_DECREF)[/+]on Apr 1, 2021
changed the title [-][C API] Fix Py_INCREF and Py_DECREF in the limited C API for Python built in debug mode[/-][+][C API] Support the limited C API in debug build (Py_INCREF and Py_DECREF)[/+]on Apr 1, 2021
changed the title [-][C API] Support the limited C API in debug build (Py_INCREF and Py_DECREF)[/-][+][C API] Support the limited C API in debug mode (Py_INCREF and Py_DECREF)[/+]on Apr 1, 2021
changed the title [-][C API] Support the limited C API in debug build (Py_INCREF and Py_DECREF)[/-][+][C API] Support the limited C API in debug mode (Py_INCREF and Py_DECREF)[/+]on Apr 1, 2021
New changeset baf10da by Victor Stinner in branch 'master':
bpo-43688: Run make regen-limited-abi (GH-25134)
With this change, "Tests / Check if generated files are up to date" job started fails (on PR 25135): "Some symbols from the limited API are missing: PyType_HasFeature".
If a function is only made of Py_INCREF() and Py_DECREF(), it can be up to 1.8x slower in the worst case. But in practice, I don't think that functions are only made of Py_INCREF() and Py_DECREF(). They do a few other things.
I'm not sure how to run a "macro benchmark" on my PR 25131, since I don't know any C extension doing anything useful. There is xxlimited, but it does almost nothing.
It's still a different ABI: "cpython-310" vs "cpython-310d" ("D" for debug). So there is risk to be confused between the stable ABI in release mode and the stable ABI in debug mode :-) I don't how how to get the ".abi3.so" suffix.
Activity
vstinner commentedon Apr 1, 2021
Currently, setup.py doesn't build xxlimited and xxlimited_35 extension modules with the limited C API if Python is built in debug mode. I only found two functions affected by Py_DEBUG macro in the limited C API: Py_INCREF() and Py_DECREF().
Example:
If Py_DEBUG is defined (Python built in debug mode), Py_INCREF() increments the private _Py_RefTotal variable.
The limited C API is supposed to provide a stable ABI, but Py_INCREF() leaks _Py_RefTotal implementation if Python is built in debug mode.
I propose to modify Py_INCREF() and Py_DECREF() of the limited C API to always declare them as opaque function calls. The regular (non limited) C API will continue to use the same static inline functions.
See also #25115 and bpo-41111 "[C API] Convert a few stdlib extensions to the limited C API (PEP-384)".
Note: Py_XINCREF() and Py_XDECREF() should be fine.
[-][C API] Fix Py_INCREF and Py_DECREF in the limited C API for Python built in debug mode[/-][+][C API] Support the limited C API in debug build (Py_INCREF and Py_DECREF)[/+][-][C API] Fix Py_INCREF and Py_DECREF in the limited C API for Python built in debug mode[/-][+][C API] Support the limited C API in debug build (Py_INCREF and Py_DECREF)[/+][-][C API] Support the limited C API in debug build (Py_INCREF and Py_DECREF)[/-][+][C API] Support the limited C API in debug mode (Py_INCREF and Py_DECREF)[/+][-][C API] Support the limited C API in debug build (Py_INCREF and Py_DECREF)[/-][+][C API] Support the limited C API in debug mode (Py_INCREF and Py_DECREF)[/+]vstinner commentedon Apr 1, 2021
One nice advantage of this change is that it becomes possible to check for reference leaks in C extensions written with the limited C API!
$ ./python -m test test_xxlimited -R 3:3 0:00:00 load avg: 2.99 Run tests sequentially 0:00:00 load avg: 2.99 [1/1] test_xxlimited beginning 6 repetitions 123456 ......== Tests result: SUCCESS ==
1 test OK.
Total duration: 367 ms
Tests result: SUCCESS
vstinner commentedon Apr 1, 2021
New changeset baf10da by Victor Stinner in branch 'master':
bpo-43688: Run make regen-limited-abi (GH-25134)
baf10da
encukou commentedon Apr 1, 2021
If you do this, please check the performance impact. Py_INCREF/Py_DECREF are very common.
vstinner commentedon Apr 1, 2021
New changeset 2ac0515 by Victor Stinner in branch 'master':
bpo-43688: Fix Py_LIMITED_API version of xxlimited (GH-25135)
2ac0515
vstinner commentedon Apr 1, 2021
With this change, "Tests / Check if generated files are up to date" job started fails (on PR 25135): "Some symbols from the limited API are missing: PyType_HasFeature".
I fixed this issue in bpo-43690 which removes PyType_HasFeature from Doc/data/stable_abi.dat.
vstinner commentedon Apr 1, 2021
I wrote a microbenchmark on Py_INCREF()+Py_DECREF():
$ python3 -m pyperf compare_to ref.json limited.json Mean +- std dev: [ref] 3.45 ns +- 0.17 ns -> [limited] 6.03 ns +- 0.21 ns: 1.75x slowerIf a function is only made of Py_INCREF() and Py_DECREF(), it can be up to 1.8x slower in the worst case. But in practice, I don't think that functions are only made of Py_INCREF() and Py_DECREF(). They do a few other things.
I'm not sure how to run a "macro benchmark" on my PR 25131, since I don't know any C extension doing anything useful. There is xxlimited, but it does almost nothing.
What would be a fair benchmark for this change?
--
To run my microbenchmark:
git apply bench.patch
./configure --with-lto --enable-optimizations
make
./python -m venv env
./env/bin/python -m pip install pyperf
./env/bin/python ../bench_limited.py -o ../limited.json -v
./env/bin/python ../bench_testcapi.py -o ../ref.json -v
vstinner commentedon Apr 2, 2021
I modified my PR 25131 to only implement Py_INCREF/Py_DECREF as opaque function calls under two conditions:
So this PR 25131 now only has an impact on performance if Python is built in debug mode. Performance on Python built in release mode is not affected.
vstinner commentedon Apr 2, 2021
In release mode, I get the libraries:
In debug mode, I get the libraries:
It's still a different ABI: "cpython-310" vs "cpython-310d" ("D" for debug). So there is risk to be confused between the stable ABI in release mode and the stable ABI in debug mode :-) I don't how how to get the ".abi3.so" suffix.
vstinner commentedon Apr 2, 2021
New changeset 3359cab by Victor Stinner in branch 'master':
bpo-43688: Support the limited C API in debug mode (GH-25131)
3359cab
vstinner commentedon Apr 2, 2021
New changeset 9bb5658 by Victor Stinner in branch 'master':
bpo-43688: Support "make regen-limited-abi" in debug mode (GH-25133)
9bb5658
vstinner commentedon May 26, 2021
Thanks for the help Petr. I close the issue, it's now fixed!