Commit 8d8feebe authored by Raymond Hettinger's avatar Raymond Hettinger

list_resize() now has an "exact" option for bypassing the overallocation

scheme in situations that likely won't benefit from it.  This further
improves memory utilization from Py2.3 which always over-allocates
except for PyList_New().

Situations expected to benefit from over-allocation:
    list.insert(), list.pop(), list.append(), and list.extend()

Situations deemed unlikely to benefit:
    list_inplace_repeat, list_ass_slice, list_ass_subscript

The most gray area was for listextend_internal() which only runs
when the argument is a list or a tuple.  This could be viewed as
a one-time fixed length addition or it could be viewed as wrapping
a series of appends.  I left its over-allocation turned on but
could be convinced otherwise.
parent e5f628b5
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#endif #endif
static int static int
list_resize(PyListObject *self, int newsize) list_resize(PyListObject *self, int newsize, int exact)
{ {
PyObject **items; PyObject **items;
size_t _new_size; size_t _new_size;
...@@ -33,7 +33,10 @@ list_resize(PyListObject *self, int newsize) ...@@ -33,7 +33,10 @@ list_resize(PyListObject *self, int newsize)
* system realloc(). * system realloc().
* The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ... * The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...
*/ */
_new_size = (newsize >> 3) + (self->ob_size < 8 ? 3 : 6) + newsize; if (exact)
_new_size = newsize;
else
_new_size = (newsize>>3) + (self->ob_size < 8 ? 3 : 6) + newsize;
items = self->ob_item; items = self->ob_item;
if (_new_size <= ((~(size_t)0) / sizeof(PyObject *))) if (_new_size <= ((~(size_t)0) / sizeof(PyObject *)))
PyMem_RESIZE(items, PyObject *, _new_size); PyMem_RESIZE(items, PyObject *, _new_size);
...@@ -152,7 +155,7 @@ ins1(PyListObject *self, int where, PyObject *v) ...@@ -152,7 +155,7 @@ ins1(PyListObject *self, int where, PyObject *v)
return -1; return -1;
} }
if (list_resize(self, n+1) == -1) if (list_resize(self, n+1, 0) == -1)
return -1; return -1;
if (where < 0) { if (where < 0) {
...@@ -518,13 +521,13 @@ list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v) ...@@ -518,13 +521,13 @@ list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v)
if (d < 0) { if (d < 0) {
memmove(&item[ihigh+d], &item[ihigh], memmove(&item[ihigh+d], &item[ihigh],
(a->ob_size - ihigh)*sizeof(PyObject *)); (a->ob_size - ihigh)*sizeof(PyObject *));
list_resize(a, a->ob_size + d); list_resize(a, a->ob_size + d, 1);
item = a->ob_item; item = a->ob_item;
} }
} }
else { /* Insert d items; recycle ihigh-ilow items */ else { /* Insert d items; recycle ihigh-ilow items */
s = a->ob_size; s = a->ob_size;
if (list_resize(a, s+d) == -1) { if (list_resize(a, s+d, 1) == -1) {
if (recycle != NULL) if (recycle != NULL)
PyMem_DEL(recycle); PyMem_DEL(recycle);
return -1; return -1;
...@@ -588,7 +591,7 @@ list_inplace_repeat(PyListObject *self, int n) ...@@ -588,7 +591,7 @@ list_inplace_repeat(PyListObject *self, int n)
return (PyObject *)self; return (PyObject *)self;
} }
if (list_resize(self, size*n) == -1) if (list_resize(self, size*n, 1) == -1)
return NULL; return NULL;
p = size; p = size;
...@@ -680,7 +683,7 @@ listextend_internal(PyListObject *self, PyObject *b) ...@@ -680,7 +683,7 @@ listextend_internal(PyListObject *self, PyObject *b)
} }
} }
if (list_resize(self, selflen + blen) == -1) { if (list_resize(self, selflen + blen, 0) == -1) {
Py_DECREF(b); Py_DECREF(b);
return -1; return -1;
} }
...@@ -733,7 +736,7 @@ listextend(PyListObject *self, PyObject *b) ...@@ -733,7 +736,7 @@ listextend(PyListObject *self, PyObject *b)
} }
m = self->ob_size; m = self->ob_size;
mn = m + n; mn = m + n;
if (list_resize(self, mn) == -1) if (list_resize(self, mn, 0) == -1)
goto error; goto error;
memset(&(self->ob_item[m]), 0, sizeof(*self->ob_item) * n); memset(&(self->ob_item[m]), 0, sizeof(*self->ob_item) * n);
...@@ -818,7 +821,7 @@ listpop(PyListObject *self, PyObject *args) ...@@ -818,7 +821,7 @@ listpop(PyListObject *self, PyObject *args)
} }
v = self->ob_item[i]; v = self->ob_item[i];
if (i == self->ob_size - 1) { if (i == self->ob_size - 1) {
if (list_resize(self, self->ob_size - 1) == -1) if (list_resize(self, self->ob_size - 1, 0) == -1)
return NULL; return NULL;
return v; return v;
} }
...@@ -2517,7 +2520,7 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value) ...@@ -2517,7 +2520,7 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
} }
self->ob_size -= slicelength; self->ob_size -= slicelength;
list_resize(self, self->ob_size); list_resize(self, self->ob_size, 1);
for (i = 0; i < slicelength; i++) { for (i = 0; i < slicelength; i++) {
Py_DECREF(garbage[i]); Py_DECREF(garbage[i]);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment