diff options
author | Raymond Hettinger <python@rcn.com> | 2004-03-14 06:42:23 (GMT) |
---|---|---|
committer | Raymond Hettinger <python@rcn.com> | 2004-03-14 06:42:23 (GMT) |
commit | 0e91643bd27132554546465d37bcc01573768aa6 (patch) | |
tree | 7837131aba76b97310b085572c7a90d0d0f82765 /Objects | |
parent | 49f9bd15ffeef67358a319f89faeaa31ad97d575 (diff) | |
download | cpython-0e91643bd27132554546465d37bcc01573768aa6.zip cpython-0e91643bd27132554546465d37bcc01573768aa6.tar.gz cpython-0e91643bd27132554546465d37bcc01573768aa6.tar.bz2 |
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.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/listobject.c | 23 |
1 files changed, 13 insertions, 10 deletions
diff --git a/Objects/listobject.c b/Objects/listobject.c index 3bda245..c8a8190 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -9,7 +9,7 @@ #endif static int -list_resize(PyListObject *self, int newsize) +list_resize(PyListObject *self, int newsize, int exact) { PyObject **items; size_t _new_size; @@ -33,7 +33,10 @@ list_resize(PyListObject *self, int newsize) * system realloc(). * 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; if (_new_size <= ((~(size_t)0) / sizeof(PyObject *))) PyMem_RESIZE(items, PyObject *, _new_size); @@ -152,7 +155,7 @@ ins1(PyListObject *self, int where, PyObject *v) return -1; } - if (list_resize(self, n+1) == -1) + if (list_resize(self, n+1, 0) == -1) return -1; if (where < 0) { @@ -518,13 +521,13 @@ list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v) if (d < 0) { memmove(&item[ihigh+d], &item[ihigh], (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; } } else { /* Insert d items; recycle ihigh-ilow items */ s = a->ob_size; - if (list_resize(a, s+d) == -1) { + if (list_resize(a, s+d, 1) == -1) { if (recycle != NULL) PyMem_DEL(recycle); return -1; @@ -588,7 +591,7 @@ list_inplace_repeat(PyListObject *self, int n) return (PyObject *)self; } - if (list_resize(self, size*n) == -1) + if (list_resize(self, size*n, 1) == -1) return NULL; p = size; @@ -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); return -1; } @@ -733,7 +736,7 @@ listextend(PyListObject *self, PyObject *b) } m = self->ob_size; mn = m + n; - if (list_resize(self, mn) == -1) + if (list_resize(self, mn, 0) == -1) goto error; memset(&(self->ob_item[m]), 0, sizeof(*self->ob_item) * n); @@ -818,7 +821,7 @@ listpop(PyListObject *self, PyObject *args) } v = self->ob_item[i]; 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 v; } @@ -2517,7 +2520,7 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value) } self->ob_size -= slicelength; - list_resize(self, self->ob_size); + list_resize(self, self->ob_size, 1); for (i = 0; i < slicelength; i++) { Py_DECREF(garbage[i]); |