Skip to content

Commit c120cae

Browse files
authored
gh-158790: Improve performance for list.insert() and del list[i] free-threaded builds (gh-158791)
1 parent ba9d96f commit c120cae

2 files changed

Lines changed: 40 additions & 5 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Speed up :meth:`list.insert` and item deletion via :keyword:`del` in free-threaded builds by using :manpage:`memmove(3)`.

‎Objects/listobject.c‎

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -478,10 +478,43 @@ end:;
478478
return ret;
479479
}
480480

481+
static void ptr_wise_atomic_memmove(PyListObject *a, PyObject **dest,
482+
PyObject **src, Py_ssize_t n);
483+
484+
static inline void
485+
list_shift_items_right_lock_held(PyListObject *self, Py_ssize_t first,
486+
Py_ssize_t last)
487+
{
488+
#ifdef Py_GIL_DISABLED
489+
ptr_wise_atomic_memmove(self, &self->ob_item[first + 1],
490+
&self->ob_item[first], last - first);
491+
#else
492+
PyObject **items = self->ob_item;
493+
for (Py_ssize_t i = last; --i >= first; ) {
494+
items[i + 1] = items[i];
495+
}
496+
#endif
497+
}
498+
499+
static inline void
500+
list_shift_items_left_lock_held(PyListObject *self, Py_ssize_t first,
501+
Py_ssize_t last)
502+
{
503+
#ifdef Py_GIL_DISABLED
504+
ptr_wise_atomic_memmove(self, &self->ob_item[first],
505+
&self->ob_item[first + 1], last - first);
506+
#else
507+
PyObject **items = self->ob_item;
508+
for (Py_ssize_t i = first; i < last; i++) {
509+
items[i] = items[i + 1];
510+
}
511+
#endif
512+
}
513+
481514
static int
482515
ins1(PyListObject *self, Py_ssize_t where, PyObject *v)
483516
{
484-
Py_ssize_t i, n = Py_SIZE(self);
517+
Py_ssize_t n = Py_SIZE(self);
485518
PyObject **items;
486519
if (v == NULL) {
487520
PyErr_BadInternalCall();
@@ -500,8 +533,9 @@ ins1(PyListObject *self, Py_ssize_t where, PyObject *v)
500533
if (where > n)
501534
where = n;
502535
items = self->ob_item;
503-
for (i = n; --i >= where; )
504-
FT_ATOMIC_STORE_PTR_RELEASE(items[i+1], items[i]);
536+
if (where < n) {
537+
list_shift_items_right_lock_held(self, where, n);
538+
}
505539
FT_ATOMIC_STORE_PTR_RELEASE(items[where], Py_NewRef(v));
506540
return 0;
507541
}
@@ -1145,8 +1179,8 @@ list_ass_item_lock_held(PyListObject *a, Py_ssize_t i, PyObject *v)
11451179
PyObject *tmp = a->ob_item[i];
11461180
if (v == NULL) {
11471181
Py_ssize_t size = Py_SIZE(a);
1148-
for (Py_ssize_t idx = i; idx < size - 1; idx++) {
1149-
FT_ATOMIC_STORE_PTR_RELEASE(a->ob_item[idx], a->ob_item[idx + 1]);
1182+
if (i < size - 1) {
1183+
list_shift_items_left_lock_held(a, i, size - 1);
11501184
}
11511185
Py_SET_SIZE(a, size - 1);
11521186
}

0 commit comments

Comments
 (0)