Remove the freelist scheme for setobjects.
The setobject freelist was consuming memory but not providing much value. Even when a freelisted setobject was available, most of the setobject fields still needed to be initialized and the small table still required a memset(). This meant that the custom freelisting scheme for sets was providing almost no incremental benefit over the default Python freelist scheme used by _PyObject_Malloc() in Objects/obmalloc.c.
This commit is contained in:
parent
ff6382b40d
commit
8f8839e10a
|
@ -105,7 +105,6 @@ PyAPI_FUNC(PyObject *) PySet_Pop(PyObject *set);
|
||||||
PyAPI_FUNC(int) _PySet_Update(PyObject *set, PyObject *iterable);
|
PyAPI_FUNC(int) _PySet_Update(PyObject *set, PyObject *iterable);
|
||||||
|
|
||||||
PyAPI_FUNC(int) PySet_ClearFreeList(void);
|
PyAPI_FUNC(int) PySet_ClearFreeList(void);
|
||||||
PyAPI_FUNC(void) _PySet_DebugMallocStats(FILE *out);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -1955,7 +1955,6 @@ _PyObject_DebugTypeStats(FILE *out)
|
||||||
_PyFrame_DebugMallocStats(out);
|
_PyFrame_DebugMallocStats(out);
|
||||||
_PyList_DebugMallocStats(out);
|
_PyList_DebugMallocStats(out);
|
||||||
_PyMethod_DebugMallocStats(out);
|
_PyMethod_DebugMallocStats(out);
|
||||||
_PySet_DebugMallocStats(out);
|
|
||||||
_PyTuple_DebugMallocStats(out);
|
_PyTuple_DebugMallocStats(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,13 +57,6 @@ PyObject *_PySet_Dummy = dummy;
|
||||||
INIT_NONZERO_SET_SLOTS(so); \
|
INIT_NONZERO_SET_SLOTS(so); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
/* Reuse scheme to save calls to malloc, free, and memset */
|
|
||||||
#ifndef PySet_MAXFREELIST
|
|
||||||
#define PySet_MAXFREELIST 80
|
|
||||||
#endif
|
|
||||||
static PySetObject *free_list[PySet_MAXFREELIST];
|
|
||||||
static int numfree = 0;
|
|
||||||
|
|
||||||
/* ======================================================================== */
|
/* ======================================================================== */
|
||||||
/* ======= Begin logic for probing the hash table ========================= */
|
/* ======= Begin logic for probing the hash table ========================= */
|
||||||
|
|
||||||
|
@ -565,10 +558,7 @@ set_dealloc(PySetObject *so)
|
||||||
}
|
}
|
||||||
if (so->table != so->smalltable)
|
if (so->table != so->smalltable)
|
||||||
PyMem_DEL(so->table);
|
PyMem_DEL(so->table);
|
||||||
if (numfree < PySet_MAXFREELIST && PyAnySet_CheckExact(so))
|
Py_TYPE(so)->tp_free(so);
|
||||||
free_list[numfree++] = so;
|
|
||||||
else
|
|
||||||
Py_TYPE(so)->tp_free(so);
|
|
||||||
Py_TRASHCAN_SAFE_END(so)
|
Py_TRASHCAN_SAFE_END(so)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1023,22 +1013,12 @@ make_new_set(PyTypeObject *type, PyObject *iterable)
|
||||||
PySetObject *so = NULL;
|
PySetObject *so = NULL;
|
||||||
|
|
||||||
/* create PySetObject structure */
|
/* create PySetObject structure */
|
||||||
if (numfree &&
|
so = (PySetObject *)type->tp_alloc(type, 0);
|
||||||
(type == &PySet_Type || type == &PyFrozenSet_Type)) {
|
if (so == NULL)
|
||||||
so = free_list[--numfree];
|
return NULL;
|
||||||
assert (so != NULL && PyAnySet_CheckExact(so));
|
/* tp_alloc has already zeroed the structure */
|
||||||
Py_TYPE(so) = type;
|
assert(so->table == NULL && so->fill == 0 && so->used == 0);
|
||||||
_Py_NewReference((PyObject *)so);
|
INIT_NONZERO_SET_SLOTS(so);
|
||||||
EMPTY_TO_MINSIZE(so);
|
|
||||||
PyObject_GC_Track(so);
|
|
||||||
} else {
|
|
||||||
so = (PySetObject *)type->tp_alloc(type, 0);
|
|
||||||
if (so == NULL)
|
|
||||||
return NULL;
|
|
||||||
/* tp_alloc has already zeroed the structure */
|
|
||||||
assert(so->table == NULL && so->fill == 0 && so->used == 0);
|
|
||||||
INIT_NONZERO_SET_SLOTS(so);
|
|
||||||
}
|
|
||||||
|
|
||||||
so->lookup = set_lookkey_unicode;
|
so->lookup = set_lookkey_unicode;
|
||||||
so->weakreflist = NULL;
|
so->weakreflist = NULL;
|
||||||
|
@ -1103,34 +1083,15 @@ frozenset_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
int
|
int
|
||||||
PySet_ClearFreeList(void)
|
PySet_ClearFreeList(void)
|
||||||
{
|
{
|
||||||
int freelist_size = numfree;
|
return 0;
|
||||||
PySetObject *so;
|
|
||||||
|
|
||||||
while (numfree) {
|
|
||||||
numfree--;
|
|
||||||
so = free_list[numfree];
|
|
||||||
PyObject_GC_Del(so);
|
|
||||||
}
|
|
||||||
return freelist_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PySet_Fini(void)
|
PySet_Fini(void)
|
||||||
{
|
{
|
||||||
PySet_ClearFreeList();
|
|
||||||
Py_CLEAR(emptyfrozenset);
|
Py_CLEAR(emptyfrozenset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print summary info about the state of the optimized allocator */
|
|
||||||
void
|
|
||||||
_PySet_DebugMallocStats(FILE *out)
|
|
||||||
{
|
|
||||||
_PyDebugAllocatorStats(out,
|
|
||||||
"free PySetObject",
|
|
||||||
numfree, sizeof(PySetObject));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
set_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
set_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue