Skip to content
Closed
Prev Previous commit
Next Next commit
Skip overallocation calc when not overallocating
  • Loading branch information
chadnetzer committed Mar 21, 2021
commit 172f2c0a4014805890ec7cbd16ea3625a569e249
40 changes: 21 additions & 19 deletions Objects/listobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,26 +58,28 @@ list_resize(PyListObject *self, Py_ssize_t newsize)
return 0;
}

/* This over-allocates proportional to the list size, making room
* for additional growth. The over-allocation is mild, but is
* enough to give linear-time amortized behavior over a long
* sequence of appends() in the presence of a poorly-performing
* system realloc().
* Add padding to make the allocated size multiple of 4.
* The growth pattern is: 0, 4, 8, 16, 24, 32, 40, 52, 64, 76, ...
* Note: new_allocated won't overflow because the largest possible value
* is PY_SSIZE_T_MAX * (9 / 8) + 6 which always fits in a size_t.
*/
new_allocated = ((size_t)newsize + (newsize >> 3) + 6) & ~(size_t)3;
/* Do not overallocate if the new size is closer to overallocated size
* than to the old size.
*/
if (newsize - Py_SIZE(self) > (Py_ssize_t)(new_allocated - newsize))
new_allocated = ((size_t)newsize + 3) & ~(size_t)3;

/* Don't overallocate for lists that start empty or are set to empty. */
if (newsize == 0 || Py_SIZE(self) == 0)
if (newsize == 0 || Py_SIZE(self) == 0) {
/* Don't overallocate for lists that start empty or are set to empty. */
new_allocated = newsize;
} else {
Comment thread
chadnetzer marked this conversation as resolved.
Outdated
/* This over-allocates proportional to the list size, making room
* for additional growth. The over-allocation is mild, but is
* enough to give linear-time amortized behavior over a long
* sequence of appends() in the presence of a poorly-performing
* system realloc().
* Add padding to make the allocated size multiple of 4.
* The growth pattern is: 0, 4, 8, 16, 24, 32, 40, 52, 64, 76, ...
* Note: new_allocated won't overflow because the largest possible value
* is PY_SSIZE_T_MAX * (9 / 8) + 6 which always fits in a size_t.
*/
new_allocated = ((size_t)newsize + (newsize >> 3) + 6) & ~(size_t)3;
/* Do not overallocate if the new size is closer to overallocated size
* than to the old size.
*/
if (newsize - Py_SIZE(self) > (Py_ssize_t)(new_allocated - newsize))
new_allocated = ((size_t)newsize + 3) & ~(size_t)3;
Comment thread
chadnetzer marked this conversation as resolved.
Outdated
}

num_allocated_bytes = new_allocated * sizeof(PyObject *);
items = (PyObject **)PyMem_Realloc(self->ob_item, num_allocated_bytes);
if (items == NULL) {
Expand Down