This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Title: Remove unused _Py_Dealloc() macro
Type: Stage: resolved
Components: C API Versions: Python 3.9
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: vstinner
Priority: normal Keywords: patch

Created on 2020-02-03 16:53 by vstinner, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 18361 merged vstinner, 2020-02-05 10:45
Messages (6)
msg361310 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2020-02-03 16:53
In bpo-35059, I converted Py_DECREF() macro to a static inline function (commit 2aaf0c12041bcaadd7f2cc5a54450eefd7a6ff12).

Then in bpo-35134, I moved _Py_Dealloc() macro to the newly created Include/cpython/object.h header file (commit 6eb996685e25c09499858bee4be258776e603c6f).

The problem is that when Py_DECREF() was converted to a static inline function, it stopped to use the *redefine* _Py_Dealloc() fast macro, but instead use the slow regular function call:

PyAPI_FUNC(void) _Py_Dealloc(PyObject *);

Py_DECREF() performance is critical for overall Python performance.

I will work on a PR to fix this issue.

See also bpo-39542 which updates object.h and cpython/object.h.
msg361341 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2020-02-04 10:26
There are different problems.

_Py_Dealloc() calls _Py_ForgetReference() and requires access to PyTypeObjects structure fields to call Py_TYPE(op)->tp_dealloc().

_Py_ForgetReference() is a function and so has no issuse with the limited API (it's not a macro nor an inline function).


* _Py_NewReference() access _Py_tracemalloc_config, _Py_RefTotal and calls _Py_AddToAllObjects()
* PyObject_INIT() and PyObject_INIT_VAR() inline functions call _Py_NewReference()

I'm not sure that it's really more efficient than _Py_NewReference() and _Py_Dealloc() are macros/inline functions. Moreover, it causes issues with the limited API and it leaks many implementation details in the API.

I may be better to convert PyObject_INIT() and PyObject_INIT_VAR() to aliases to public opaque PyObject_Init() and PyObject_InitVar(), and convert _Py_NewReference() and _Py_Dealloc() to opaque functions (from the API point of view).
msg361347 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2020-02-04 14:45
For _Py_NewReference(), I proposed PR 18346 to make it opaque (hide implementation details).
msg361349 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2020-02-04 15:00
To declare _Py_Dealloc() as a static inline function in Include/object.h, we need to define the PyTypeObject in object.h which requires tons on other type definitions: PyNumberMethods, PySequenceMethods, etc.

If possible, I would prefer to not move back CPython specific definitions from cpython/object.h to object.h. It would mean to keep the Python 3.8 state: leave _Py_Dealloc() defined as a regular function and close this issue as "won't fix".
msg361419 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2020-02-05 10:51
I wrote a quick & dirty local patch to define again _Py_NewReference() and _Py_Dealloc() as inline function in object.h before Py_DECREF(). I failed to see a clear win in term of performance.


./python -m pyperf timeit --duplicate=4096 'o=object(); o=None' -l 512

Result if _Py_Dealloc() is inlined again:

Mean +- std dev: [opaque] 69.3 ns +- 1.5 ns -> [dealloc] 67.5 ns +- 1.5 ns: 1.03x faster (-3%)

Result if _Py_Dealloc() and _Py_NewReference() are inlined again:

Mean +- std dev: [opaque] 69.3 ns +- 1.5 ns -> [dealloc_newref] 66.1 ns +- 1.3 ns: 1.05x faster (-5%)

It's a matter of 3.2 nanoseconds. Honestly, I don't think that it's worth it to bother with that. I expect way more siginificant speedup with more advanced optimizations like using a tracing GC or tagged pointers, and these optimizations require to better hide implementation details.

_Py_Dealloc() was converted to a regular function was mistake when I moved code to cpython/object.h and nobody noticed.

For all these reasons, I wrote PR 18361 to remove the unused _Py_Dealloc() macro, rather than trying to inline it again.
msg361420 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2020-02-05 11:18
New changeset f16433a73138f279642e581074135694ddcfe965 by Victor Stinner in branch 'master':
bpo-39543: Remove unused _Py_Dealloc() macro (GH-18361)
Date User Action Args
2022-04-11 14:59:26adminsetgithub: 83724
2020-02-05 11:19:38vstinnersetstatus: open -> closed
title: Py_DECREF(): use inlined _Py_Dealloc() -> Remove unused _Py_Dealloc() macro
stage: patch review -> resolved
resolution: fixed
versions: - Python 3.8
2020-02-05 11:18:59vstinnersetmessages: + msg361420
2020-02-05 10:51:32vstinnersetmessages: + msg361419
2020-02-05 10:45:37vstinnersetkeywords: + patch
stage: patch review
pull_requests: + pull_request17736
2020-02-04 15:00:36vstinnersetmessages: + msg361349
2020-02-04 14:45:57vstinnersetmessages: + msg361347
2020-02-04 10:26:35vstinnersetmessages: + msg361341
2020-02-03 16:53:48vstinnercreate