From d4e44270c640d127ab22658a0b7e6762deaa07fb Mon Sep 17 00:00:00 2001 From: Cody Maloney Date: Wed, 28 Oct 2026 01:06:03 -0700 Subject: [PATCH 1/2] gh-160858: Use the list freelist in list() list() allocated its result with PyType_GenericAlloc(), bypassing the freelist that PyList_New() and the [] display use. For an exact list, allocate with PyList_New(0) instead. The object handed to list.__init__() is in the same state either way: empty, with no item array, and tracked by the GC. Subclasses still use PyType_GenericAlloc(). pyperf, PGO+LTO, base 19270d3bbb5, two interleaved rounds per side (a third round, disturbed by machine load, was dropped): | Benchmark | main | branch | |----------------|:-------:|:---------------------:| | list() | 21.2 ns | 15.3 ns: 1.38x faster | | list(d) | 36.1 ns | 27.4 ns: 1.32x faster | | list(t) | 30.3 ns | 23.9 ns: 1.27x faster | | list(l) | 32.0 ns | 25.7 ns: 1.24x faster | | list(r) | 43.6 ns | 36.0 ns: 1.21x faster | | x + 1 | 10.4 ns | 9.70 ns: 1.07x faster | | len(l) | 9.87 ns | 9.53 ns: 1.03x faster | | l[0] | 8.24 ns | 8.00 ns: 1.03x faster | | L(t) | 48.2 ns | 47.4 ns: 1.02x faster | | tuple(l) | 15.4 ns | 16.0 ns: 1.04x slower | | Geometric mean | (ref) | 1.13x faster | Not significant: []. x + 1, len(l), l[0], L(t) and tuple(l) don't run the changed code; their movement is layout noise, within the up-to-1.07x spread between two runs of the same main build. Co-Authored-By: Claude Opus 5.5 --- .../2026-10-28-17-00-22.gh-issue-160858.JPGbOK.rst | 2 ++ Objects/listobject.c | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-10-28-17-00-22.gh-issue-160858.JPGbOK.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-10-28-17-00-22.gh-issue-160858.JPGbOK.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-28-17-00-22.gh-issue-160858.JPGbOK.rst new file mode 100644 index 000000000000000..334a89553597170 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-28-17-00-22.gh-issue-160858.JPGbOK.rst @@ -0,0 +1,2 @@ +Speed up :class:`list` construction by reusing list objects from the free +list, as ``[]`` already does. diff --git a/Objects/listobject.c b/Objects/listobject.c index a01f40d57181da5..4384a850780b7fd 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -3600,7 +3600,7 @@ static int list___init___impl(PyListObject *self, PyObject *iterable) /*[clinic end generated code: output=0f3c21379d01de48 input=b3f3fe7206af8f6b]*/ { - /* Verify list invariants established by PyType_GenericAlloc() */ + /* Verify list invariants */ assert(0 <= Py_SIZE(self)); assert(Py_SIZE(self) <= self->allocated || self->allocated == -1); assert(self->ob_item != NULL || @@ -3632,7 +3632,10 @@ list_vectorcall(PyObject *type, PyObject * const*args, return NULL; } - PyObject *list = PyType_GenericAlloc(_PyType_CAST(type), 0); + /* use PyList_New() to make exact lists from the freelist. */ + PyObject *list = (type == (PyObject *)&PyList_Type + ? PyList_New(0) + : PyType_GenericAlloc(_PyType_CAST(type), 0)); if (list == NULL) { return NULL; } From 04bd0704d95848d6de7b855c788946eabbbe1760 Mon Sep 17 00:00:00 2001 From: Cody Maloney Date: Thu, 29 Oct 2026 09:55:31 -0700 Subject: [PATCH 2/2] Remove NEWS --- .../2026-10-28-17-00-22.gh-issue-160858.JPGbOK.rst | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-10-28-17-00-22.gh-issue-160858.JPGbOK.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-10-28-17-00-22.gh-issue-160858.JPGbOK.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-10-28-17-00-22.gh-issue-160858.JPGbOK.rst deleted file mode 100644 index 334a89553597170..000000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-10-28-17-00-22.gh-issue-160858.JPGbOK.rst +++ /dev/null @@ -1,2 +0,0 @@ -Speed up :class:`list` construction by reusing list objects from the free -list, as ``[]`` already does.