Skip to content

Commit 8f8839e

Browse files
committed
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.
1 parent ff6382b commit 8f8839e

File tree

3 files changed

+8
-49
lines changed

3 files changed

+8
-49
lines changed

Include/setobject.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ PyAPI_FUNC(PyObject *) PySet_Pop(PyObject *set);
105105
PyAPI_FUNC(int) _PySet_Update(PyObject *set, PyObject *iterable);
106106

107107
PyAPI_FUNC(int) PySet_ClearFreeList(void);
108-
PyAPI_FUNC(void) _PySet_DebugMallocStats(FILE *out);
109108
#endif
110109

111110
#ifdef __cplusplus

Objects/object.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1955,7 +1955,6 @@ _PyObject_DebugTypeStats(FILE *out)
19551955
_PyFrame_DebugMallocStats(out);
19561956
_PyList_DebugMallocStats(out);
19571957
_PyMethod_DebugMallocStats(out);
1958-
_PySet_DebugMallocStats(out);
19591958
_PyTuple_DebugMallocStats(out);
19601959
}
19611960

Objects/setobject.c

Lines changed: 8 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,6 @@ PyObject *_PySet_Dummy = dummy;
5757
INIT_NONZERO_SET_SLOTS(so); \
5858
} while(0)
5959

60-
/* Reuse scheme to save calls to malloc, free, and memset */
61-
#ifndef PySet_MAXFREELIST
62-
#define PySet_MAXFREELIST 80
63-
#endif
64-
static PySetObject *free_list[PySet_MAXFREELIST];
65-
static int numfree = 0;
66-
6760
/* ======================================================================== */
6861
/* ======= Begin logic for probing the hash table ========================= */
6962

@@ -565,10 +558,7 @@ set_dealloc(PySetObject *so)
565558
}
566559
if (so->table != so->smalltable)
567560
PyMem_DEL(so->table);
568-
if (numfree < PySet_MAXFREELIST && PyAnySet_CheckExact(so))
569-
free_list[numfree++] = so;
570-
else
571-
Py_TYPE(so)->tp_free(so);
561+
Py_TYPE(so)->tp_free(so);
572562
Py_TRASHCAN_SAFE_END(so)
573563
}
574564

@@ -1023,22 +1013,12 @@ make_new_set(PyTypeObject *type, PyObject *iterable)
10231013
PySetObject *so = NULL;
10241014

10251015
/* create PySetObject structure */
1026-
if (numfree &&
1027-
(type == &PySet_Type || type == &PyFrozenSet_Type)) {
1028-
so = free_list[--numfree];
1029-
assert (so != NULL && PyAnySet_CheckExact(so));
1030-
Py_TYPE(so) = type;
1031-
_Py_NewReference((PyObject *)so);
1032-
EMPTY_TO_MINSIZE(so);
1033-
PyObject_GC_Track(so);
1034-
} else {
1035-
so = (PySetObject *)type->tp_alloc(type, 0);
1036-
if (so == NULL)
1037-
return NULL;
1038-
/* tp_alloc has already zeroed the structure */
1039-
assert(so->table == NULL && so->fill == 0 && so->used == 0);
1040-
INIT_NONZERO_SET_SLOTS(so);
1041-
}
1016+
so = (PySetObject *)type->tp_alloc(type, 0);
1017+
if (so == NULL)
1018+
return NULL;
1019+
/* tp_alloc has already zeroed the structure */
1020+
assert(so->table == NULL && so->fill == 0 && so->used == 0);
1021+
INIT_NONZERO_SET_SLOTS(so);
10421022

10431023
so->lookup = set_lookkey_unicode;
10441024
so->weakreflist = NULL;
@@ -1103,34 +1083,15 @@ frozenset_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
11031083
int
11041084
PySet_ClearFreeList(void)
11051085
{
1106-
int freelist_size = numfree;
1107-
PySetObject *so;
1108-
1109-
while (numfree) {
1110-
numfree--;
1111-
so = free_list[numfree];
1112-
PyObject_GC_Del(so);
1113-
}
1114-
return freelist_size;
1086+
return 0;
11151087
}
11161088

11171089
void
11181090
PySet_Fini(void)
11191091
{
1120-
PySet_ClearFreeList();
11211092
Py_CLEAR(emptyfrozenset);
11221093
}
11231094

1124-
/* Print summary info about the state of the optimized allocator */
1125-
void
1126-
_PySet_DebugMallocStats(FILE *out)
1127-
{
1128-
_PyDebugAllocatorStats(out,
1129-
"free PySetObject",
1130-
numfree, sizeof(PySetObject));
1131-
}
1132-
1133-
11341095
static PyObject *
11351096
set_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
11361097
{

0 commit comments

Comments
 (0)