SF #1022910: Conserve memory with list.pop()

The list resizing scheme only downsized when more than 16 elements were
removed in a single step:  del a[100:120].   As a result, the list would
never shrink when popping elements off one at a time.

This patch makes it shrink whenever more than half of the space is unused.

Also, at Tim's suggestion, renamed _new_size to new_allocated.  This makes
the code easier to understand.
This commit is contained in:
Raymond Hettinger 2004-09-12 19:53:07 +00:00
parent 0e9980f75a
commit a84f3abb9e
1 changed files with 11 additions and 8 deletions

View File

@ -25,13 +25,14 @@ static int
list_resize(PyListObject *self, int newsize)
{
PyObject **items;
size_t _new_size;
size_t new_allocated;
int allocated = self->allocated;
/* Bypass realloc() when a previous overallocation is large enough
to accommodate the newsize. If the newsize is 16 smaller than the
current size, then proceed with the realloc() to shrink the list.
to accommodate the newsize. If the newsize falls lower than half
the allocated size, then proceed with the realloc() to shrink the list.
*/
if (self->allocated >= newsize && self->ob_size < newsize + 16) {
if (allocated >= newsize && newsize >= (allocated >> 1)) {
assert(self->ob_item != NULL || newsize == 0);
self->ob_size = newsize;
return 0;
@ -44,10 +45,12 @@ 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;
new_allocated = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize;
if (newsize == 0)
new_allocated = 0;
items = self->ob_item;
if (_new_size <= ((~(size_t)0) / sizeof(PyObject *)))
PyMem_RESIZE(items, PyObject *, _new_size);
if (new_allocated <= ((~(size_t)0) / sizeof(PyObject *)))
PyMem_RESIZE(items, PyObject *, new_allocated);
else
items = NULL;
if (items == NULL) {
@ -56,7 +59,7 @@ list_resize(PyListObject *self, int newsize)
}
self->ob_item = items;
self->ob_size = newsize;
self->allocated = _new_size;
self->allocated = new_allocated;
return 0;
}