bpo-37340: remove free_list for bound method objects (GH-14232)
This commit is contained in:
parent
76b645124b
commit
3e54b57531
|
@ -99,11 +99,6 @@ typedef struct {
|
||||||
|
|
||||||
PyAPI_FUNC(int) PyCFunction_ClearFreeList(void);
|
PyAPI_FUNC(int) PyCFunction_ClearFreeList(void);
|
||||||
|
|
||||||
#ifndef Py_LIMITED_API
|
|
||||||
PyAPI_FUNC(void) _PyCFunction_DebugMallocStats(FILE *out);
|
|
||||||
PyAPI_FUNC(void) _PyMethod_DebugMallocStats(FILE *out);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
Removed object cache (``free_list``) for bound method objects. Temporary
|
||||||
|
bound method objects are less used than before thanks to the ``LOAD_METHOD``
|
||||||
|
opcode and the ``_PyObject_VectorcallMethod`` C API.
|
|
@ -8,15 +8,6 @@
|
||||||
|
|
||||||
#define TP_DESCR_GET(t) ((t)->tp_descr_get)
|
#define TP_DESCR_GET(t) ((t)->tp_descr_get)
|
||||||
|
|
||||||
/* Free list for method objects to safe malloc/free overhead
|
|
||||||
* The im_self element is used to chain the elements.
|
|
||||||
*/
|
|
||||||
static PyMethodObject *free_list;
|
|
||||||
static int numfree = 0;
|
|
||||||
#ifndef PyMethod_MAXFREELIST
|
|
||||||
#define PyMethod_MAXFREELIST 256
|
|
||||||
#endif
|
|
||||||
|
|
||||||
_Py_IDENTIFIER(__name__);
|
_Py_IDENTIFIER(__name__);
|
||||||
_Py_IDENTIFIER(__qualname__);
|
_Py_IDENTIFIER(__qualname__);
|
||||||
|
|
||||||
|
@ -103,21 +94,13 @@ method_vectorcall(PyObject *method, PyObject *const *args,
|
||||||
PyObject *
|
PyObject *
|
||||||
PyMethod_New(PyObject *func, PyObject *self)
|
PyMethod_New(PyObject *func, PyObject *self)
|
||||||
{
|
{
|
||||||
PyMethodObject *im;
|
|
||||||
if (self == NULL) {
|
if (self == NULL) {
|
||||||
PyErr_BadInternalCall();
|
PyErr_BadInternalCall();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
im = free_list;
|
PyMethodObject *im = PyObject_GC_New(PyMethodObject, &PyMethod_Type);
|
||||||
if (im != NULL) {
|
if (im == NULL) {
|
||||||
free_list = (PyMethodObject *)(im->im_self);
|
return NULL;
|
||||||
(void)PyObject_INIT(im, &PyMethod_Type);
|
|
||||||
numfree--;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
im = PyObject_GC_New(PyMethodObject, &PyMethod_Type);
|
|
||||||
if (im == NULL)
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
im->im_weakreflist = NULL;
|
im->im_weakreflist = NULL;
|
||||||
Py_INCREF(func);
|
Py_INCREF(func);
|
||||||
|
@ -252,14 +235,7 @@ method_dealloc(PyMethodObject *im)
|
||||||
PyObject_ClearWeakRefs((PyObject *)im);
|
PyObject_ClearWeakRefs((PyObject *)im);
|
||||||
Py_DECREF(im->im_func);
|
Py_DECREF(im->im_func);
|
||||||
Py_XDECREF(im->im_self);
|
Py_XDECREF(im->im_self);
|
||||||
if (numfree < PyMethod_MAXFREELIST) {
|
PyObject_GC_Del(im);
|
||||||
im->im_self = (PyObject *)free_list;
|
|
||||||
free_list = im;
|
|
||||||
numfree++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
PyObject_GC_Del(im);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -395,16 +371,7 @@ PyTypeObject PyMethod_Type = {
|
||||||
int
|
int
|
||||||
PyMethod_ClearFreeList(void)
|
PyMethod_ClearFreeList(void)
|
||||||
{
|
{
|
||||||
int freelist_size = numfree;
|
return 0;
|
||||||
|
|
||||||
while (free_list) {
|
|
||||||
PyMethodObject *im = free_list;
|
|
||||||
free_list = (PyMethodObject *)(im->im_self);
|
|
||||||
PyObject_GC_Del(im);
|
|
||||||
numfree--;
|
|
||||||
}
|
|
||||||
assert(numfree == 0);
|
|
||||||
return freelist_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -413,15 +380,6 @@ PyMethod_Fini(void)
|
||||||
(void)PyMethod_ClearFreeList();
|
(void)PyMethod_ClearFreeList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print summary info about the state of the optimized allocator */
|
|
||||||
void
|
|
||||||
_PyMethod_DebugMallocStats(FILE *out)
|
|
||||||
{
|
|
||||||
_PyDebugAllocatorStats(out,
|
|
||||||
"free PyMethodObject",
|
|
||||||
numfree, sizeof(PyMethodObject));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------
|
||||||
* instance method
|
* instance method
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -7,15 +7,6 @@
|
||||||
#include "pycore_pystate.h"
|
#include "pycore_pystate.h"
|
||||||
#include "structmember.h"
|
#include "structmember.h"
|
||||||
|
|
||||||
/* Free list for method objects to safe malloc/free overhead
|
|
||||||
* The m_self element is used to chain the objects.
|
|
||||||
*/
|
|
||||||
static PyCFunctionObject *free_list = NULL;
|
|
||||||
static int numfree = 0;
|
|
||||||
#ifndef PyCFunction_MAXFREELIST
|
|
||||||
#define PyCFunction_MAXFREELIST 256
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* undefine macro trampoline to PyCFunction_NewEx */
|
/* undefine macro trampoline to PyCFunction_NewEx */
|
||||||
#undef PyCFunction_New
|
#undef PyCFunction_New
|
||||||
|
|
||||||
|
@ -66,17 +57,10 @@ PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyCFunctionObject *op;
|
PyCFunctionObject *op =
|
||||||
op = free_list;
|
PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
|
||||||
if (op != NULL) {
|
if (op == NULL) {
|
||||||
free_list = (PyCFunctionObject *)(op->m_self);
|
return NULL;
|
||||||
(void)PyObject_INIT(op, &PyCFunction_Type);
|
|
||||||
numfree--;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
|
|
||||||
if (op == NULL)
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
op->m_weakreflist = NULL;
|
op->m_weakreflist = NULL;
|
||||||
op->m_ml = ml;
|
op->m_ml = ml;
|
||||||
|
@ -130,14 +114,7 @@ meth_dealloc(PyCFunctionObject *m)
|
||||||
}
|
}
|
||||||
Py_XDECREF(m->m_self);
|
Py_XDECREF(m->m_self);
|
||||||
Py_XDECREF(m->m_module);
|
Py_XDECREF(m->m_module);
|
||||||
if (numfree < PyCFunction_MAXFREELIST) {
|
PyObject_GC_Del(m);
|
||||||
m->m_self = (PyObject *)free_list;
|
|
||||||
free_list = m;
|
|
||||||
numfree++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
PyObject_GC_Del(m);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -338,16 +315,7 @@ PyTypeObject PyCFunction_Type = {
|
||||||
int
|
int
|
||||||
PyCFunction_ClearFreeList(void)
|
PyCFunction_ClearFreeList(void)
|
||||||
{
|
{
|
||||||
int freelist_size = numfree;
|
return 0;
|
||||||
|
|
||||||
while (free_list) {
|
|
||||||
PyCFunctionObject *v = free_list;
|
|
||||||
free_list = (PyCFunctionObject *)(v->m_self);
|
|
||||||
PyObject_GC_Del(v);
|
|
||||||
numfree--;
|
|
||||||
}
|
|
||||||
assert(numfree == 0);
|
|
||||||
return freelist_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -356,15 +324,6 @@ PyCFunction_Fini(void)
|
||||||
(void)PyCFunction_ClearFreeList();
|
(void)PyCFunction_ClearFreeList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print summary info about the state of the optimized allocator */
|
|
||||||
void
|
|
||||||
_PyCFunction_DebugMallocStats(FILE *out)
|
|
||||||
{
|
|
||||||
_PyDebugAllocatorStats(out,
|
|
||||||
"free PyCFunctionObject",
|
|
||||||
numfree, sizeof(PyCFunctionObject));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Vectorcall functions for each of the PyCFunction calling conventions,
|
/* Vectorcall functions for each of the PyCFunction calling conventions,
|
||||||
* except for METH_VARARGS (possibly combined with METH_KEYWORDS) which
|
* except for METH_VARARGS (possibly combined with METH_KEYWORDS) which
|
||||||
|
|
|
@ -1959,12 +1959,10 @@ Py_ssize_t (*_Py_abstract_hack)(PyObject *) = PyObject_Size;
|
||||||
void
|
void
|
||||||
_PyObject_DebugTypeStats(FILE *out)
|
_PyObject_DebugTypeStats(FILE *out)
|
||||||
{
|
{
|
||||||
_PyCFunction_DebugMallocStats(out);
|
|
||||||
_PyDict_DebugMallocStats(out);
|
_PyDict_DebugMallocStats(out);
|
||||||
_PyFloat_DebugMallocStats(out);
|
_PyFloat_DebugMallocStats(out);
|
||||||
_PyFrame_DebugMallocStats(out);
|
_PyFrame_DebugMallocStats(out);
|
||||||
_PyList_DebugMallocStats(out);
|
_PyList_DebugMallocStats(out);
|
||||||
_PyMethod_DebugMallocStats(out);
|
|
||||||
_PyTuple_DebugMallocStats(out);
|
_PyTuple_DebugMallocStats(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue