]> granicus.if.org Git - python/commitdiff
SF patch #947476: Apply freelist technique to lists
authorRaymond Hettinger <python@rcn.com>
Wed, 5 May 2004 05:37:53 +0000 (05:37 +0000)
committerRaymond Hettinger <python@rcn.com>
Wed, 5 May 2004 05:37:53 +0000 (05:37 +0000)
Re-use list object bodies.  Saves calls to malloc() and free() for
faster list instantiation and deallocation.

Misc/NEWS
Objects/listobject.c

index c26b09b33fdf6c243e631eef3def1ccc9094c1b2..983c54888297e00c484e0b595b3c694fd19b907f 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -54,6 +54,9 @@ Core and builtins
   the overallocation is no more than three elements -- this improves space
   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
   as the dict() constructor.  This now includes item lists and/or
   keyword arguments.
index 7a2cdeaf31f006aa265e96636ada0a252168967b..f3aee395c6cb7f74943ae02b8b51e74b3a2ad64d 100644 (file)
@@ -49,6 +49,11 @@ list_resize(PyListObject *self, int newsize)
        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 *
 PyList_New(int size)
 {
@@ -63,9 +68,14 @@ PyList_New(int size)
        if (nbytes / sizeof(PyObject *) != (size_t)size) {
                return PyErr_NoMemory();
        }
-       op = PyObject_GC_New(PyListObject, &PyList_Type);
-       if (op == NULL) {
-               return NULL;
+       if (num_free_lists) {
+               num_free_lists--;
+               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) {
                op->ob_item = NULL;
@@ -233,7 +243,10 @@ list_dealloc(PyListObject *op)
                }
                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)
 }