From 2e0280b490429f360a49844810c138302f4692da Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Fri, 8 Nov 2024 12:43:03 +0100 Subject: [PATCH 1/3] Use freelist for range object --- Include/internal/pycore_freelist_state.h | 2 ++ Objects/rangeobject.c | 15 ++++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/Include/internal/pycore_freelist_state.h b/Include/internal/pycore_freelist_state.h index 4e04cf431e0b31..70c0403b32ba83 100644 --- a/Include/internal/pycore_freelist_state.h +++ b/Include/internal/pycore_freelist_state.h @@ -15,6 +15,7 @@ extern "C" { # define Py_dictkeys_MAXFREELIST 80 # define Py_floats_MAXFREELIST 100 # define Py_slices_MAXFREELIST 1 +# define Py_ranges_MAXFREELIST 10 # define Py_contexts_MAXFREELIST 255 # define Py_async_gens_MAXFREELIST 80 # define Py_async_gen_asends_MAXFREELIST 80 @@ -40,6 +41,7 @@ struct _Py_freelists { struct _Py_freelist dicts; struct _Py_freelist dictkeys; struct _Py_freelist slices; + struct _Py_freelist ranges; struct _Py_freelist contexts; struct _Py_freelist async_gens; struct _Py_freelist async_gen_asends; diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c index 2942ab624edf72..959b4f91733aed 100644 --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -3,6 +3,7 @@ #include "Python.h" #include "pycore_abstract.h" // _PyIndex_Check() #include "pycore_ceval.h" // _PyEval_GetBuiltin() +#include "pycore_freelist.h" // _Py_FREELIST_FREE(), _Py_FREELIST_POP() #include "pycore_long.h" // _PyLong_GetZero() #include "pycore_modsupport.h" // _PyArg_NoKwnames() #include "pycore_range.h" @@ -51,16 +52,20 @@ static rangeobject * make_range_object(PyTypeObject *type, PyObject *start, PyObject *stop, PyObject *step) { - rangeobject *obj = NULL; PyObject *length; length = compute_range_length(start, stop, step); if (length == NULL) { return NULL; } - obj = PyObject_New(rangeobject, type); + rangeobject *obj = _Py_FREELIST_POP(rangeobject, ranges); if (obj == NULL) { - Py_DECREF(length); - return NULL; + obj = PyObject_New(rangeobject, type); + if (obj == NULL) { + Py_DECREF(length); + return NULL; + } + } else { + //printf("rangeobject from freelist!\n"); } obj->start = start; obj->stop = stop; @@ -170,7 +175,7 @@ range_dealloc(rangeobject *r) Py_DECREF(r->stop); Py_DECREF(r->step); Py_DECREF(r->length); - PyObject_Free(r); + _Py_FREELIST_FREE(ranges, r, PyObject_Free); } static unsigned long From ffde646050fa2fa126b775402c98c77e4d629352 Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Fri, 8 Nov 2024 12:59:25 +0100 Subject: [PATCH 2/3] Use freelist for rangeiter object --- Include/internal/pycore_freelist_state.h | 2 ++ Objects/rangeobject.c | 17 +++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Include/internal/pycore_freelist_state.h b/Include/internal/pycore_freelist_state.h index 70c0403b32ba83..169fd62f9ee45b 100644 --- a/Include/internal/pycore_freelist_state.h +++ b/Include/internal/pycore_freelist_state.h @@ -16,6 +16,7 @@ extern "C" { # define Py_floats_MAXFREELIST 100 # define Py_slices_MAXFREELIST 1 # define Py_ranges_MAXFREELIST 10 +# define Py_rangeiters_MAXFREELIST 10 # define Py_contexts_MAXFREELIST 255 # define Py_async_gens_MAXFREELIST 80 # define Py_async_gen_asends_MAXFREELIST 80 @@ -42,6 +43,7 @@ struct _Py_freelists { struct _Py_freelist dictkeys; struct _Py_freelist slices; struct _Py_freelist ranges; + struct _Py_freelist rangeiters; struct _Py_freelist contexts; struct _Py_freelist async_gens; struct _Py_freelist async_gen_asends; diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c index 959b4f91733aed..8df6d95df22047 100644 --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -885,6 +885,12 @@ rangeiter_setstate(_PyRangeIterObject *r, PyObject *state) Py_RETURN_NONE; } +static void +rangeiter_dealloc(_PyRangeIterObject *r) +{ + _Py_FREELIST_FREE(rangeiters, r, PyObject_Free); +} + PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); @@ -904,7 +910,7 @@ PyTypeObject PyRangeIter_Type = { sizeof(_PyRangeIterObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - (destructor)PyObject_Free, /* tp_dealloc */ + (destructor)rangeiter_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -965,9 +971,12 @@ get_len_of_range(long lo, long hi, long step) static PyObject * fast_range_iter(long start, long stop, long step, long len) { - _PyRangeIterObject *it = PyObject_New(_PyRangeIterObject, &PyRangeIter_Type); - if (it == NULL) - return NULL; + _PyRangeIterObject *it = _Py_FREELIST_POP(_PyRangeIterObject, rangeiters); + if (it == NULL) { + it = PyObject_New(_PyRangeIterObject, &PyRangeIter_Type); + if (it == NULL) + return NULL; + } it->start = start; it->step = step; it->len = len; From a08176a7a360f4551513cc30711a2fb3fefe99a6 Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Mon, 11 Nov 2024 22:26:34 +0100 Subject: [PATCH 3/3] cleanup debug code --- Objects/rangeobject.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c index 8df6d95df22047..f6627abfbded64 100644 --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -64,8 +64,6 @@ make_range_object(PyTypeObject *type, PyObject *start, Py_DECREF(length); return NULL; } - } else { - //printf("rangeobject from freelist!\n"); } obj->start = start; obj->stop = stop;