summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2020-03-17 21:46:00 (GMT)
committerGitHub <noreply@github.com>2020-03-17 21:46:00 (GMT)
commit2fe815edd6778fb9deef8f8044848647659c2eb8 (patch)
treec22add59ac05b77cbc9b767f18b0d54768e8b463
parentd469d666b874ae746ca9a17bbfc9dbbf6fb2d6bc (diff)
downloadcpython-2fe815edd6778fb9deef8f8044848647659c2eb8.zip
cpython-2fe815edd6778fb9deef8f8044848647659c2eb8.tar.gz
cpython-2fe815edd6778fb9deef8f8044848647659c2eb8.tar.bz2
bpo-38373: Change list overallocating strategy. (GH-18952)
* Add padding to make the allocated size multiple of 4. * Do not overallocate if the new size is closer to overalocated size than to the old size.
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2020-03-11-12-28-16.bpo-38373.FE9S21.rst2
-rw-r--r--Objects/listobject.c14
2 files changed, 10 insertions, 6 deletions
diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-03-11-12-28-16.bpo-38373.FE9S21.rst b/Misc/NEWS.d/next/Core and Builtins/2020-03-11-12-28-16.bpo-38373.FE9S21.rst
new file mode 100644
index 0000000..83d60e0
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2020-03-11-12-28-16.bpo-38373.FE9S21.rst
@@ -0,0 +1,2 @@
+Chaged list overallocation strategy. It no longer overallocates if the new
+size is closer to overalocated size than to the old size and adds padding.
diff --git a/Objects/listobject.c b/Objects/listobject.c
index 46bc777..4e2b6a9 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -54,15 +54,17 @@ list_resize(PyListObject *self, Py_ssize_t newsize)
* enough to give linear-time amortized behavior over a long
* sequence of appends() in the presence of a poorly-performing
* system realloc().
- * The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...
+ * 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) + (newsize < 9 ? 3 : 6);
- if (new_allocated > (size_t)PY_SSIZE_T_MAX / sizeof(PyObject *)) {
- PyErr_NoMemory();
- return -1;
- }
+ new_allocated = ((size_t)newsize + (newsize >> 3) + 6) & ~(size_t)3;
+ /* Do not overallocate if the new size is closer to overalocated 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;
if (newsize == 0)
new_allocated = 0;