Unified naming convention for free lists and their limits. All free lists

in Object/ are named ``free_list``, the counter ``numfree`` and the upper
limit is a macro ``PyName_MAXFREELIST`` inside an #ifndef block.

The chances should make it easier to adjust Python for platforms with
less memory, e.g. mobile phones.
This commit is contained in:
Christian Heimes 2008-02-06 13:33:44 +00:00
parent 6075a82243
commit 5b970ad483
9 changed files with 99 additions and 84 deletions

View File

@ -1487,6 +1487,10 @@ Build
C API C API
----- -----
- Unified naming convention for free lists and their limits. All free lists
in Object/ are named ``free_list``, the counter ``numfree`` and the upper
limit is a macro ``PyName_MAXFREELIST`` inside an #ifndef block.
- ``PySet_Add()`` can now modify a newly created frozenset. Similarly to - ``PySet_Add()`` can now modify a newly created frozenset. Similarly to
``PyTuple_SetItem``, it can be used to populate a brand new frozenset; but ``PyTuple_SetItem``, it can be used to populate a brand new frozenset; but
it does not steal a reference to the added item. it does not steal a reference to the added item.

View File

@ -9,7 +9,9 @@
*/ */
static PyMethodObject *free_list; static PyMethodObject *free_list;
static int numfree = 0; static int numfree = 0;
#define MAXFREELIST 256 #ifndef PyMethod_MAXFREELIST
#define PyMethod_MAXFREELIST 256
#endif
#define TP_DESCR_GET(t) \ #define TP_DESCR_GET(t) \
(PyType_HasFeature(t, Py_TPFLAGS_HAVE_CLASS) ? (t)->tp_descr_get : NULL) (PyType_HasFeature(t, Py_TPFLAGS_HAVE_CLASS) ? (t)->tp_descr_get : NULL)
@ -2337,7 +2339,7 @@ instancemethod_dealloc(register PyMethodObject *im)
Py_DECREF(im->im_func); Py_DECREF(im->im_func);
Py_XDECREF(im->im_self); Py_XDECREF(im->im_self);
Py_XDECREF(im->im_class); Py_XDECREF(im->im_class);
if (numfree < MAXFREELIST) { if (numfree < PyMethod_MAXFREELIST) {
im->im_self = (PyObject *)free_list; im->im_self = (PyObject *)free_list;
free_list = im; free_list = im;
numfree++; numfree++;

View File

@ -183,9 +183,11 @@ show_counts(void)
} while(0) } while(0)
/* Dictionary reuse scheme to save calls to malloc, free, and memset */ /* Dictionary reuse scheme to save calls to malloc, free, and memset */
#define MAXFREEDICTS 80 #ifndef PyDict_MAXFREELIST
static PyDictObject *free_dicts[MAXFREEDICTS]; #define PyDict_MAXFREELIST 80
static int num_free_dicts = 0; #endif
static PyDictObject *free_list[PyDict_MAXFREELIST];
static int numfree = 0;
PyObject * PyObject *
PyDict_New(void) PyDict_New(void)
@ -199,8 +201,8 @@ PyDict_New(void)
Py_AtExit(show_counts); Py_AtExit(show_counts);
#endif #endif
} }
if (num_free_dicts) { if (numfree) {
mp = free_dicts[--num_free_dicts]; mp = free_list[--numfree];
assert (mp != NULL); assert (mp != NULL);
assert (Py_TYPE(mp) == &PyDict_Type); assert (Py_TYPE(mp) == &PyDict_Type);
_Py_NewReference((PyObject *)mp); _Py_NewReference((PyObject *)mp);
@ -868,8 +870,8 @@ dict_dealloc(register PyDictObject *mp)
} }
if (mp->ma_table != mp->ma_smalltable) if (mp->ma_table != mp->ma_smalltable)
PyMem_DEL(mp->ma_table); PyMem_DEL(mp->ma_table);
if (num_free_dicts < MAXFREEDICTS && Py_TYPE(mp) == &PyDict_Type) if (numfree < PyDict_MAXFREELIST && Py_TYPE(mp) == &PyDict_Type)
free_dicts[num_free_dicts++] = mp; free_list[numfree++] = mp;
else else
Py_TYPE(mp)->tp_free((PyObject *)mp); Py_TYPE(mp)->tp_free((PyObject *)mp);
Py_TRASHCAN_SAFE_END(mp) Py_TRASHCAN_SAFE_END(mp)

View File

@ -393,14 +393,15 @@ static PyGetSetDef frame_getsetlist[] = {
call depth of more than 20 or 30 is probably already exceptional call depth of more than 20 or 30 is probably already exceptional
unless the program contains run-away recursion. I hope. unless the program contains run-away recursion. I hope.
Later, MAXFREELIST was added to bound the # of frames saved on Later, PyFrame_MAXFREELIST was added to bound the # of frames saved on
free_list. Else programs creating lots of cyclic trash involving free_list. Else programs creating lots of cyclic trash involving
frames could provoke free_list into growing without bound. frames could provoke free_list into growing without bound.
*/ */
static PyFrameObject *free_list = NULL; static PyFrameObject *free_list = NULL;
static int numfree = 0; /* number of frames currently in free_list */ static int numfree = 0; /* number of frames currently in free_list */
#define MAXFREELIST 200 /* max value for numfree */ /* max value for numfree */
#define PyFrame_MAXFREELIST 200
static void static void
frame_dealloc(PyFrameObject *f) frame_dealloc(PyFrameObject *f)
@ -433,7 +434,7 @@ frame_dealloc(PyFrameObject *f)
co = f->f_code; co = f->f_code;
if (co->co_zombieframe == NULL) if (co->co_zombieframe == NULL)
co->co_zombieframe = f; co->co_zombieframe = f;
else if (numfree < MAXFREELIST) { else if (numfree < PyFrame_MAXFREELIST) {
++numfree; ++numfree;
f->f_back = free_list; f->f_back = free_list;
free_list = f; free_list = f;

View File

@ -64,18 +64,20 @@ list_resize(PyListObject *self, Py_ssize_t newsize)
} }
/* Empty list reuse scheme to save calls to malloc and free */ /* Empty list reuse scheme to save calls to malloc and free */
#define MAXFREELISTS 80 #ifndef PyList_MAXFREELIST
static PyListObject *free_lists[MAXFREELISTS]; #define PyList_MAXFREELIST 80
static int num_free_lists = 0; #endif
static PyListObject *free_list[PyList_MAXFREELIST];
static int numfree = 0;
void void
PyList_Fini(void) PyList_Fini(void)
{ {
PyListObject *op; PyListObject *op;
while (num_free_lists) { while (numfree) {
num_free_lists--; numfree--;
op = free_lists[num_free_lists]; op = free_list[numfree];
assert(PyList_CheckExact(op)); assert(PyList_CheckExact(op));
PyObject_GC_Del(op); PyObject_GC_Del(op);
} }
@ -95,9 +97,9 @@ PyList_New(Py_ssize_t size)
/* Check for overflow */ /* Check for overflow */
if (nbytes / sizeof(PyObject *) != (size_t)size) if (nbytes / sizeof(PyObject *) != (size_t)size)
return PyErr_NoMemory(); return PyErr_NoMemory();
if (num_free_lists) { if (numfree) {
num_free_lists--; numfree--;
op = free_lists[num_free_lists]; op = free_list[numfree];
_Py_NewReference((PyObject *)op); _Py_NewReference((PyObject *)op);
} else { } else {
op = PyObject_GC_New(PyListObject, &PyList_Type); op = PyObject_GC_New(PyListObject, &PyList_Type);
@ -265,8 +267,8 @@ list_dealloc(PyListObject *op)
} }
PyMem_FREE(op->ob_item); PyMem_FREE(op->ob_item);
} }
if (num_free_lists < MAXFREELISTS && PyList_CheckExact(op)) if (numfree < PyList_MAXFREELIST && PyList_CheckExact(op))
free_lists[num_free_lists++] = op; free_list[numfree++] = op;
else else
Py_TYPE(op)->tp_free((PyObject *)op); Py_TYPE(op)->tp_free((PyObject *)op);
Py_TRASHCAN_SAFE_END(op) Py_TRASHCAN_SAFE_END(op)

View File

@ -9,7 +9,9 @@
*/ */
static PyCFunctionObject *free_list = NULL; static PyCFunctionObject *free_list = NULL;
static int numfree = 0; static int numfree = 0;
#define MAXFREELIST 256 #ifndef PyCFunction_MAXFREELIST
#define PyCFunction_MAXFREELIST 256
#endif
PyObject * PyObject *
PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module) PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)
@ -131,7 +133,7 @@ meth_dealloc(PyCFunctionObject *m)
_PyObject_GC_UNTRACK(m); _PyObject_GC_UNTRACK(m);
Py_XDECREF(m->m_self); Py_XDECREF(m->m_self);
Py_XDECREF(m->m_module); Py_XDECREF(m->m_module);
if (numfree < MAXFREELIST) { if (numfree < PyCFunction_MAXFREELIST) {
m->m_self = (PyObject *)free_list; m->m_self = (PyObject *)free_list;
free_list = m; free_list = m;
numfree++; numfree++;

View File

@ -51,9 +51,11 @@ _PySet_Dummy(void)
} while(0) } while(0)
/* Reuse scheme to save calls to malloc, free, and memset */ /* Reuse scheme to save calls to malloc, free, and memset */
#define MAXFREESETS 80 #ifndef PySet_MAXFREELIST
static PySetObject *free_sets[MAXFREESETS]; #define PySet_MAXFREELIST 80
static int num_free_sets = 0; #endif
static PySetObject *free_list[PySet_MAXFREELIST];
static int numfree = 0;
/* /*
The basic lookup function used by all operations. The basic lookup function used by all operations.
@ -558,8 +560,8 @@ set_dealloc(PySetObject *so)
} }
if (so->table != so->smalltable) if (so->table != so->smalltable)
PyMem_DEL(so->table); PyMem_DEL(so->table);
if (num_free_sets < MAXFREESETS && PyAnySet_CheckExact(so)) if (numfree < PySet_MAXFREELIST && PyAnySet_CheckExact(so))
free_sets[num_free_sets++] = so; free_list[numfree++] = so;
else else
Py_TYPE(so)->tp_free(so); Py_TYPE(so)->tp_free(so);
Py_TRASHCAN_SAFE_END(so) Py_TRASHCAN_SAFE_END(so)
@ -983,9 +985,9 @@ make_new_set(PyTypeObject *type, PyObject *iterable)
} }
/* create PySetObject structure */ /* create PySetObject structure */
if (num_free_sets && if (numfree &&
(type == &PySet_Type || type == &PyFrozenSet_Type)) { (type == &PySet_Type || type == &PyFrozenSet_Type)) {
so = free_sets[--num_free_sets]; so = free_list[--numfree];
assert (so != NULL && PyAnySet_CheckExact(so)); assert (so != NULL && PyAnySet_CheckExact(so));
Py_TYPE(so) = type; Py_TYPE(so) = type;
_Py_NewReference((PyObject *)so); _Py_NewReference((PyObject *)so);
@ -1053,9 +1055,9 @@ PySet_Fini(void)
{ {
PySetObject *so; PySetObject *so;
while (num_free_sets) { while (numfree) {
num_free_sets--; numfree--;
so = free_sets[num_free_sets]; so = free_list[numfree];
PyObject_GC_Del(so); PyObject_GC_Del(so);
} }
Py_CLEAR(dummy); Py_CLEAR(dummy);

View File

@ -4,19 +4,19 @@
#include "Python.h" #include "Python.h"
/* Speed optimization to avoid frequent malloc/free of small tuples */ /* Speed optimization to avoid frequent malloc/free of small tuples */
#ifndef MAXSAVESIZE #ifndef PyTuple_MAXSAVESIZE
#define MAXSAVESIZE 20 /* Largest tuple to save on free list */ #define PyTuple_MAXSAVESIZE 20 /* Largest tuple to save on free list */
#endif #endif
#ifndef MAXSAVEDTUPLES #ifndef PyTuple_MAXFREELIST
#define MAXSAVEDTUPLES 2000 /* Maximum number of tuples of each size to save */ #define PyTuple_MAXFREELIST 2000 /* Maximum number of tuples of each size to save */
#endif #endif
#if MAXSAVESIZE > 0 #if PyTuple_MAXSAVESIZE > 0
/* Entries 1 up to MAXSAVESIZE are free lists, entry 0 is the empty /* Entries 1 up to PyTuple_MAXSAVESIZE are free lists, entry 0 is the empty
tuple () of which at most one instance will be allocated. tuple () of which at most one instance will be allocated.
*/ */
static PyTupleObject *free_tuples[MAXSAVESIZE]; static PyTupleObject *free_list[PyTuple_MAXSAVESIZE];
static int num_free_tuples[MAXSAVESIZE]; static int numfree[PyTuple_MAXSAVESIZE];
#endif #endif
#ifdef COUNT_ALLOCS #ifdef COUNT_ALLOCS
int fast_tuple_allocs; int fast_tuple_allocs;
@ -32,18 +32,18 @@ PyTuple_New(register Py_ssize_t size)
PyErr_BadInternalCall(); PyErr_BadInternalCall();
return NULL; return NULL;
} }
#if MAXSAVESIZE > 0 #if PyTuple_MAXSAVESIZE > 0
if (size == 0 && free_tuples[0]) { if (size == 0 && free_list[0]) {
op = free_tuples[0]; op = free_list[0];
Py_INCREF(op); Py_INCREF(op);
#ifdef COUNT_ALLOCS #ifdef COUNT_ALLOCS
tuple_zero_allocs++; tuple_zero_allocs++;
#endif #endif
return (PyObject *) op; return (PyObject *) op;
} }
if (size < MAXSAVESIZE && (op = free_tuples[size]) != NULL) { if (size < PyTuple_MAXSAVESIZE && (op = free_list[size]) != NULL) {
free_tuples[size] = (PyTupleObject *) op->ob_item[0]; free_list[size] = (PyTupleObject *) op->ob_item[0];
num_free_tuples[size]--; numfree[size]--;
#ifdef COUNT_ALLOCS #ifdef COUNT_ALLOCS
fast_tuple_allocs++; fast_tuple_allocs++;
#endif #endif
@ -71,10 +71,10 @@ PyTuple_New(register Py_ssize_t size)
} }
for (i=0; i < size; i++) for (i=0; i < size; i++)
op->ob_item[i] = NULL; op->ob_item[i] = NULL;
#if MAXSAVESIZE > 0 #if PyTuple_MAXSAVESIZE > 0
if (size == 0) { if (size == 0) {
free_tuples[0] = op; free_list[0] = op;
++num_free_tuples[0]; ++numfree[0];
Py_INCREF(op); /* extra INCREF so that this is never freed */ Py_INCREF(op); /* extra INCREF so that this is never freed */
} }
#endif #endif
@ -167,14 +167,14 @@ tupledealloc(register PyTupleObject *op)
i = len; i = len;
while (--i >= 0) while (--i >= 0)
Py_XDECREF(op->ob_item[i]); Py_XDECREF(op->ob_item[i]);
#if MAXSAVESIZE > 0 #if PyTuple_MAXSAVESIZE > 0
if (len < MAXSAVESIZE && if (len < PyTuple_MAXSAVESIZE &&
num_free_tuples[len] < MAXSAVEDTUPLES && numfree[len] < PyTuple_MAXFREELIST &&
Py_TYPE(op) == &PyTuple_Type) Py_TYPE(op) == &PyTuple_Type)
{ {
op->ob_item[0] = (PyObject *) free_tuples[len]; op->ob_item[0] = (PyObject *) free_list[len];
num_free_tuples[len]++; numfree[len]++;
free_tuples[len] = op; free_list[len] = op;
goto done; /* return */ goto done; /* return */
} }
#endif #endif
@ -781,16 +781,16 @@ _PyTuple_Resize(PyObject **pv, Py_ssize_t newsize)
void void
PyTuple_Fini(void) PyTuple_Fini(void)
{ {
#if MAXSAVESIZE > 0 #if PyTuple_MAXSAVESIZE > 0
int i; int i;
Py_XDECREF(free_tuples[0]); Py_XDECREF(free_list[0]);
free_tuples[0] = NULL; free_list[0] = NULL;
for (i = 1; i < MAXSAVESIZE; i++) { for (i = 1; i < PyTuple_MAXSAVESIZE; i++) {
PyTupleObject *p, *q; PyTupleObject *p, *q;
p = free_tuples[i]; p = free_list[i];
free_tuples[i] = NULL; free_list[i] = NULL;
while (p) { while (p) {
q = p; q = p;
p = (PyTupleObject *)(p->ob_item[0]); p = (PyTupleObject *)(p->ob_item[0]);

View File

@ -51,7 +51,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* Limit for the Unicode object free list */ /* Limit for the Unicode object free list */
#define MAX_UNICODE_FREELIST_SIZE 1024 #define PyUnicode_MAXFREELIST 1024
/* Limit for the Unicode object free list stay alive optimization. /* Limit for the Unicode object free list stay alive optimization.
@ -59,7 +59,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
all objects on the free list having a size less than this all objects on the free list having a size less than this
limit. This reduces malloc() overhead for small Unicode objects. limit. This reduces malloc() overhead for small Unicode objects.
At worst this will result in MAX_UNICODE_FREELIST_SIZE * At worst this will result in PyUnicode_MAXFREELIST *
(sizeof(PyUnicodeObject) + KEEPALIVE_SIZE_LIMIT + (sizeof(PyUnicodeObject) + KEEPALIVE_SIZE_LIMIT +
malloc()-overhead) bytes of unused garbage. malloc()-overhead) bytes of unused garbage.
@ -93,8 +93,8 @@ extern "C" {
#endif #endif
/* Free list for Unicode objects */ /* Free list for Unicode objects */
static PyUnicodeObject *unicode_freelist; static PyUnicodeObject *free_list;
static int unicode_freelist_size; static int numfree;
/* The empty Unicode object is shared to improve performance. */ /* The empty Unicode object is shared to improve performance. */
static PyUnicodeObject *unicode_empty; static PyUnicodeObject *unicode_empty;
@ -299,10 +299,10 @@ PyUnicodeObject *_PyUnicode_New(Py_ssize_t length)
} }
/* Unicode freelist & memory allocation */ /* Unicode freelist & memory allocation */
if (unicode_freelist) { if (free_list) {
unicode = unicode_freelist; unicode = free_list;
unicode_freelist = *(PyUnicodeObject **)unicode; free_list = *(PyUnicodeObject **)unicode;
unicode_freelist_size--; numfree--;
if (unicode->str) { if (unicode->str) {
/* Keep-Alive optimization: we only upsize the buffer, /* Keep-Alive optimization: we only upsize the buffer,
never downsize it. */ never downsize it. */
@ -352,7 +352,7 @@ static
void unicode_dealloc(register PyUnicodeObject *unicode) void unicode_dealloc(register PyUnicodeObject *unicode)
{ {
if (PyUnicode_CheckExact(unicode) && if (PyUnicode_CheckExact(unicode) &&
unicode_freelist_size < MAX_UNICODE_FREELIST_SIZE) { numfree < PyUnicode_MAXFREELIST) {
/* Keep-Alive optimization */ /* Keep-Alive optimization */
if (unicode->length >= KEEPALIVE_SIZE_LIMIT) { if (unicode->length >= KEEPALIVE_SIZE_LIMIT) {
PyMem_DEL(unicode->str); PyMem_DEL(unicode->str);
@ -364,9 +364,9 @@ void unicode_dealloc(register PyUnicodeObject *unicode)
unicode->defenc = NULL; unicode->defenc = NULL;
} }
/* Add to free list */ /* Add to free list */
*(PyUnicodeObject **)unicode = unicode_freelist; *(PyUnicodeObject **)unicode = free_list;
unicode_freelist = unicode; free_list = unicode;
unicode_freelist_size++; numfree++;
} }
else { else {
PyMem_DEL(unicode->str); PyMem_DEL(unicode->str);
@ -7704,9 +7704,9 @@ unicode_zfill(PyUnicodeObject *self, PyObject *args)
#if 0 #if 0
static PyObject* static PyObject*
unicode_freelistsize(PyUnicodeObject *self) free_listsize(PyUnicodeObject *self)
{ {
return PyInt_FromLong(unicode_freelist_size); return PyInt_FromLong(numfree);
} }
#endif #endif
@ -7861,7 +7861,7 @@ static PyMethodDef unicode_methods[] = {
#if 0 #if 0
/* This one is just used for debugging the implementation. */ /* This one is just used for debugging the implementation. */
{"freelistsize", (PyCFunction) unicode_freelistsize, METH_NOARGS}, {"freelistsize", (PyCFunction) free_listsize, METH_NOARGS},
#endif #endif
{"__getnewargs__", (PyCFunction)unicode_getnewargs, METH_NOARGS}, {"__getnewargs__", (PyCFunction)unicode_getnewargs, METH_NOARGS},
@ -8831,8 +8831,8 @@ void _PyUnicode_Init(void)
}; };
/* Init the implementation */ /* Init the implementation */
unicode_freelist = NULL; free_list = NULL;
unicode_freelist_size = 0; numfree = 0;
unicode_empty = _PyUnicode_New(0); unicode_empty = _PyUnicode_New(0);
if (!unicode_empty) if (!unicode_empty)
return; return;
@ -8869,7 +8869,7 @@ _PyUnicode_Fini(void)
} }
} }
for (u = unicode_freelist; u != NULL;) { for (u = free_list; u != NULL;) {
PyUnicodeObject *v = u; PyUnicodeObject *v = u;
u = *(PyUnicodeObject **)u; u = *(PyUnicodeObject **)u;
if (v->str) if (v->str)
@ -8877,8 +8877,8 @@ _PyUnicode_Fini(void)
Py_XDECREF(v->defenc); Py_XDECREF(v->defenc);
PyObject_Del(v); PyObject_Del(v);
} }
unicode_freelist = NULL; free_list = NULL;
unicode_freelist_size = 0; numfree = 0;
} }
#ifdef __cplusplus #ifdef __cplusplus