Skip to content

Commit b3da698

Browse files
authored
gh-94603: micro optimize list.pop (gh-94604)
1 parent ce39aaf commit b3da698

File tree

2 files changed

+21
-12
lines changed

2 files changed

+21
-12
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Improve performance of ``list.pop`` for small lists.

Objects/listobject.c

+20-12
Original file line numberDiff line numberDiff line change
@@ -1022,21 +1022,29 @@ list_pop_impl(PyListObject *self, Py_ssize_t index)
10221022
PyErr_SetString(PyExc_IndexError, "pop index out of range");
10231023
return NULL;
10241024
}
1025-
v = self->ob_item[index];
1026-
if (index == Py_SIZE(self) - 1) {
1027-
status = list_resize(self, Py_SIZE(self) - 1);
1028-
if (status >= 0)
1029-
return v; /* and v now owns the reference the list had */
1030-
else
1031-
return NULL;
1025+
1026+
PyObject **items = self->ob_item;
1027+
v = items[index];
1028+
const Py_ssize_t size_after_pop = Py_SIZE(self) - 1;
1029+
if (size_after_pop == 0) {
1030+
Py_INCREF(v);
1031+
status = _list_clear(self);
10321032
}
1033-
Py_INCREF(v);
1034-
status = list_ass_slice(self, index, index+1, (PyObject *)NULL);
1035-
if (status < 0) {
1036-
Py_DECREF(v);
1033+
else {
1034+
if ((size_after_pop - index) > 0) {
1035+
memmove(&items[index], &items[index+1], (size_after_pop - index) * sizeof(PyObject *));
1036+
}
1037+
status = list_resize(self, size_after_pop);
1038+
}
1039+
if (status >= 0) {
1040+
return v; // and v now owns the reference the list had
1041+
}
1042+
else {
1043+
// list resize failed, need to restore
1044+
memmove(&items[index+1], &items[index], (size_after_pop - index)* sizeof(PyObject *));
1045+
items[index] = v;
10371046
return NULL;
10381047
}
1039-
return v;
10401048
}
10411049

10421050
/* Reverse a slice of a list in place, from lo up to (exclusive) hi. */

0 commit comments

Comments
 (0)