SF patch #947476: Apply freelist technique to lists

Re-use list object bodies.  Saves calls to malloc() and free() for
faster list instantiation and deallocation.
This commit is contained in:
Raymond Hettinger 2004-05-05 05:37:53 +00:00
parent 8aa8c84d18
commit 0468e416c1
2 changed files with 20 additions and 4 deletions

View File

@ -54,6 +54,9 @@ Core and builtins
the overallocation is no more than three elements -- this improves space the overallocation is no more than three elements -- this improves space
utilization for applications that have large numbers of small lists. utilization for applications that have large numbers of small lists.
- Most list bodies now get re-used rather than freed. Speeds up list
instantiation and deletion by saving calls to malloc() and free().
- The dict.update() method now accepts all the same argument forms - The dict.update() method now accepts all the same argument forms
as the dict() constructor. This now includes item lists and/or as the dict() constructor. This now includes item lists and/or
keyword arguments. keyword arguments.

View File

@ -49,6 +49,11 @@ list_resize(PyListObject *self, int newsize)
return 0; return 0;
} }
/* Empty list reuse scheme to save calls to malloc and free */
#define MAXFREELISTS 80
static PyListObject *free_lists[MAXFREELISTS];
static int num_free_lists = 0;
PyObject * PyObject *
PyList_New(int size) PyList_New(int size)
{ {
@ -63,9 +68,14 @@ PyList_New(int size)
if (nbytes / sizeof(PyObject *) != (size_t)size) { if (nbytes / sizeof(PyObject *) != (size_t)size) {
return PyErr_NoMemory(); return PyErr_NoMemory();
} }
op = PyObject_GC_New(PyListObject, &PyList_Type); if (num_free_lists) {
if (op == NULL) { num_free_lists--;
return NULL; op = free_lists[num_free_lists];
_Py_NewReference((PyObject *)op);
} else {
op = PyObject_GC_New(PyListObject, &PyList_Type);
if (op == NULL)
return NULL;
} }
if (size <= 0) { if (size <= 0) {
op->ob_item = NULL; op->ob_item = NULL;
@ -233,7 +243,10 @@ list_dealloc(PyListObject *op)
} }
PyMem_FREE(op->ob_item); PyMem_FREE(op->ob_item);
} }
op->ob_type->tp_free((PyObject *)op); if (num_free_lists < MAXFREELISTS && PyList_CheckExact(op))
free_lists[num_free_lists++] = op;
else
op->ob_type->tp_free((PyObject *)op);
Py_TRASHCAN_SAFE_END(op) Py_TRASHCAN_SAFE_END(op)
} }