https://github.com/python/cpython/commit/e431a7a72312468d853f0e46353193d969017eca
commit: e431a7a72312468d853f0e46353193d969017eca
branch: 3.15
author: Donghee Na <[email protected]>
committer: corona10 <[email protected]>
date: 2026-10-10T09:32:10+09:00
summary:
[3.15] gh-158592: Skip reallocation when shrinking a small list (GH-158787)
(gh-159001)
files:
A
Misc/NEWS.d/next/Core_and_Builtins/2026-10-02-16-19-35.gh-issue-158592.V6W21J.rst
A
Misc/NEWS.d/next/Core_and_Builtins/2026-10-04-11-59-33.gh-issue-158592._BpoeY.rst
M Objects/listobject.c
diff --git
a/Misc/NEWS.d/next/Core_and_Builtins/2026-10-02-16-19-35.gh-issue-158592.V6W21J.rst
b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-02-16-19-35.gh-issue-158592.V6W21J.rst
new file mode 100644
index 00000000000000..1112ca8e63d314
--- /dev/null
+++
b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-02-16-19-35.gh-issue-158592.V6W21J.rst
@@ -0,0 +1 @@
+``del list[index]`` now triggers shrinking the list's internal array.
diff --git
a/Misc/NEWS.d/next/Core_and_Builtins/2026-10-04-11-59-33.gh-issue-158592._BpoeY.rst
b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-04-11-59-33.gh-issue-158592._BpoeY.rst
new file mode 100644
index 00000000000000..d937a81cc4630a
--- /dev/null
+++
b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-04-11-59-33.gh-issue-158592._BpoeY.rst
@@ -0,0 +1,2 @@
+Skip the array reallocation when shrinking a small :class:`list`. Patch by
+Donghee Na.
diff --git a/Objects/listobject.c b/Objects/listobject.c
index 9f059ec875d7ea..b6ebb2b53fc304 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -91,6 +91,10 @@ ensure_shared_on_resize(PyListObject *self)
#endif
}
+#define LIST_SMALL_ALLOCATED 32
+
+static int py_list_resize(PyListObject *self, Py_ssize_t newsize);
+
/* Ensure ob_item has room for at least newsize elements, and set
* ob_size to newsize. If newsize > ob_size on entry, the content
* of the new slots at exit is undefined heap trash; it's the caller's
@@ -99,22 +103,37 @@ ensure_shared_on_resize(PyListObject *self)
* Failure is impossible if newsize <= self.allocated on entry.
* Note that self->ob_item may change, and even if newsize is less
* than ob_size on entry.
+ *
+ * Always inlining list_resize() makes the fast path a few instructions
+ * in each caller instead of a function call.
*/
-static int
+static inline Py_ALWAYS_INLINE int
list_resize(PyListObject *self, Py_ssize_t newsize)
{
- size_t new_allocated, target_bytes;
Py_ssize_t allocated = self->allocated;
/* Bypass realloc() when a previous overallocation is large enough
to accommodate the newsize. If the newsize falls lower than half
the allocated size, then proceed with the realloc() to shrink the list.
+ gh-158592: do not shrink a small list, the realloc() cost is bigger
+ than the memory we get back.
*/
- if (allocated >= newsize && newsize >= (allocated >> 1)) {
+ if (allocated >= newsize
+ && (newsize >= (allocated >> 1) || allocated <= LIST_SMALL_ALLOCATED))
+ {
assert(self->ob_item != NULL || newsize == 0);
Py_SET_SIZE(self, newsize);
return 0;
}
+ return py_list_resize(self, newsize);
+}
+
+/* Slow path of list_resize(): allocate or reallocate ob_item. */
+static int
+py_list_resize(PyListObject *self, Py_ssize_t newsize)
+{
+ size_t new_allocated, target_bytes;
+ Py_ssize_t allocated = self->allocated;
/* This over-allocates proportional to the list size, making room
* for additional growth. The over-allocation is mild, but is
@@ -136,6 +155,8 @@ list_resize(PyListObject *self, Py_ssize_t newsize)
if (newsize == 0)
new_allocated = 0;
+ assert(newsize > allocated || new_allocated < (size_t)allocated);
+
ensure_shared_on_resize(self);
#ifdef Py_GIL_DISABLED
@@ -1148,7 +1169,7 @@ list_ass_item_lock_held(PyListObject *a, Py_ssize_t i,
PyObject *v)
for (Py_ssize_t idx = i; idx < size - 1; idx++) {
FT_ATOMIC_STORE_PTR_RELEASE(a->ob_item[idx], a->ob_item[idx + 1]);
}
- Py_SET_SIZE(a, size - 1);
+ list_resize(a, size - 1); // NB: shrinking a list can't fail
}
else {
FT_ATOMIC_STORE_PTR_RELEASE(a->ob_item[i], Py_NewRef(v));
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]