From cb834902f6ffd45ec4c442bfac281614810f1453 Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Fri, 8 Nov 2024 12:43:03 +0100 Subject: [PATCH 1/9] 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 a1a94c1f2dc880..daeebf35900a38 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_ints_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 @@ -42,6 +43,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 6adf31c33f1576e130917269cb4703fa79c73997 Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Fri, 8 Nov 2024 12:59:25 +0100 Subject: [PATCH 2/9] 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 daeebf35900a38..873bd0623a2a2f 100644 --- a/Include/internal/pycore_freelist_state.h +++ b/Include/internal/pycore_freelist_state.h @@ -17,6 +17,7 @@ extern "C" { # define Py_ints_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 @@ -44,6 +45,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 94cbc7c988653a99a574f2195e541f9effd2e81f Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Mon, 11 Nov 2024 22:26:34 +0100 Subject: [PATCH 3/9] 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; From 17100c09debfa6aadc1ac5e747aa16a96688c74c Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Thu, 12 Dec 2024 22:50:45 +0100 Subject: [PATCH 4/9] set types --- Include/internal/pycore_freelist.h | 1 + Include/internal/pycore_freelist_state.h | 4 ++-- Objects/listobject.c | 16 ++++++++++------ Objects/rangeobject.c | 7 +++++-- Objects/tupleobject.c | 15 +++++++++++---- Objects/typeobject.c | 1 + 6 files changed, 30 insertions(+), 14 deletions(-) diff --git a/Include/internal/pycore_freelist.h b/Include/internal/pycore_freelist.h index 84a5ab30f3eeea..54b472189f1796 100644 --- a/Include/internal/pycore_freelist.h +++ b/Include/internal/pycore_freelist.h @@ -40,6 +40,7 @@ _Py_freelists_GET(void) #define _Py_FREELIST_POP(TYPE, NAME) \ _Py_CAST(TYPE*, _PyFreeList_Pop(&_Py_freelists_GET()->NAME)) + // Pops a non-PyObject data structure from the freelist, returns NULL if the // freelist is empty. #define _Py_FREELIST_POP_MEM(NAME) \ diff --git a/Include/internal/pycore_freelist_state.h b/Include/internal/pycore_freelist_state.h index 873bd0623a2a2f..db8363aa8c75ce 100644 --- a/Include/internal/pycore_freelist_state.h +++ b/Include/internal/pycore_freelist_state.h @@ -17,7 +17,7 @@ extern "C" { # define Py_ints_MAXFREELIST 100 # define Py_slices_MAXFREELIST 1 # define Py_ranges_MAXFREELIST 10 -# define Py_rangeiters_MAXFREELIST 10 +# define Py_shared_iters_MAXFREELIST 24 # define Py_contexts_MAXFREELIST 255 # define Py_async_gens_MAXFREELIST 80 # define Py_async_gen_asends_MAXFREELIST 80 @@ -45,7 +45,7 @@ struct _Py_freelists { struct _Py_freelist dictkeys; struct _Py_freelist slices; struct _Py_freelist ranges; - struct _Py_freelist rangeiters; + struct _Py_freelist shared_iters; struct _Py_freelist contexts; struct _Py_freelist async_gens; struct _Py_freelist async_gen_asends; diff --git a/Objects/listobject.c b/Objects/listobject.c index a877bad66be45f..c91ebe42a0f638 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -3910,15 +3910,19 @@ PyTypeObject PyListIter_Type = { static PyObject * list_iter(PyObject *seq) { - _PyListIterObject *it; - if (!PyList_Check(seq)) { PyErr_BadInternalCall(); return NULL; } - it = PyObject_GC_New(_PyListIterObject, &PyListIter_Type); - if (it == NULL) - return NULL; + _PyListIterObject *it = _Py_FREELIST_POP(_PyListIterObject, shared_iters); + if (it == NULL) { + it = PyObject_GC_New(_PyListIterObject, &PyListIter_Type); + if (it == NULL) { + return NULL; + } + } else { + Py_SET_TYPE(it, &PyListIter_Type); + } it->it_index = 0; it->it_seq = (PyListObject *)Py_NewRef(seq); _PyObject_GC_TRACK(it); @@ -3931,7 +3935,7 @@ listiter_dealloc(PyObject *self) _PyListIterObject *it = (_PyListIterObject *)self; _PyObject_GC_UNTRACK(it); Py_XDECREF(it->it_seq); - PyObject_GC_Del(it); + _Py_FREELIST_FREE(shared_iters, it, PyObject_GC_Del); } static int diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c index f6627abfbded64..529525e106b3c6 100644 --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -886,7 +886,7 @@ rangeiter_setstate(_PyRangeIterObject *r, PyObject *state) static void rangeiter_dealloc(_PyRangeIterObject *r) { - _Py_FREELIST_FREE(rangeiters, r, PyObject_Free); + _Py_FREELIST_FREE(shared_iters, r, PyObject_Free); } PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); @@ -969,12 +969,15 @@ 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 = _Py_FREELIST_POP(_PyRangeIterObject, rangeiters); + _PyRangeIterObject *it = _Py_FREELIST_POP(_PyRangeIterObject, shared_iters); if (it == NULL) { it = PyObject_New(_PyRangeIterObject, &PyRangeIter_Type); if (it == NULL) return NULL; } + else { + Py_SET_TYPE(it, &PyRangeIter_Type); + } it->start = start; it->step = step; it->len = len; diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 49977726eadca9..d2a18f8f7ac11b 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -994,7 +994,8 @@ tupleiter_dealloc(_PyTupleIterObject *it) { _PyObject_GC_UNTRACK(it); Py_XDECREF(it->it_seq); - PyObject_GC_Del(it); + assert(sizeof(_PyTupleIterObject)==sizeof(_PyListIterObject)); + _Py_FREELIST_FREE(shared_iters, it, PyObject_GC_Del); } static int @@ -1122,9 +1123,15 @@ tuple_iter(PyObject *seq) PyErr_BadInternalCall(); return NULL; } - it = PyObject_GC_New(_PyTupleIterObject, &PyTupleIter_Type); - if (it == NULL) - return NULL; + it = _Py_FREELIST_POP(_PyTupleIterObject, shared_iters); + + if (it == NULL) { + it = PyObject_GC_New(_PyTupleIterObject, &PyTupleIter_Type); + if (it == NULL) + return NULL; + } else { + Py_SET_TYPE(it, &PyTupleIter_Type); + } it->it_index = 0; it->it_seq = (PyTupleObject *)Py_NewRef(seq); _PyObject_GC_TRACK(it); diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 7f95b519561e68..4b4cf993395b9e 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -6,6 +6,7 @@ #include "pycore_code.h" // CO_FAST_FREE #include "pycore_dict.h" // _PyDict_KeysSize() #include "pycore_frame.h" // _PyInterpreterFrame +#include "pycore_freelist.h" // _Py_FREELIST_FREE(), _Py_FREELIST_POP() #include "pycore_lock.h" // _PySeqLock_* #include "pycore_long.h" // _PyLong_IsNegative(), _PyLong_GetOne() #include "pycore_memoryobject.h" // _PyMemoryView_FromBufferProc() From ea98fa1477d27539089c927d64e149c94e9ddbb1 Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Mon, 30 Dec 2024 23:11:14 +0100 Subject: [PATCH 5/9] add more freelists --- Include/internal/pycore_freelist.h | 1 - Include/internal/pycore_freelist_state.h | 2 ++ Objects/classobject.c | 11 ++++++++--- Objects/iterobject.c | 17 +++++++++++++---- Objects/typeobject.c | 1 - 5 files changed, 23 insertions(+), 9 deletions(-) diff --git a/Include/internal/pycore_freelist.h b/Include/internal/pycore_freelist.h index 54b472189f1796..84a5ab30f3eeea 100644 --- a/Include/internal/pycore_freelist.h +++ b/Include/internal/pycore_freelist.h @@ -40,7 +40,6 @@ _Py_freelists_GET(void) #define _Py_FREELIST_POP(TYPE, NAME) \ _Py_CAST(TYPE*, _PyFreeList_Pop(&_Py_freelists_GET()->NAME)) - // Pops a non-PyObject data structure from the freelist, returns NULL if the // freelist is empty. #define _Py_FREELIST_POP_MEM(NAME) \ diff --git a/Include/internal/pycore_freelist_state.h b/Include/internal/pycore_freelist_state.h index db8363aa8c75ce..dfbb5105292642 100644 --- a/Include/internal/pycore_freelist_state.h +++ b/Include/internal/pycore_freelist_state.h @@ -18,6 +18,7 @@ extern "C" { # define Py_slices_MAXFREELIST 1 # define Py_ranges_MAXFREELIST 10 # define Py_shared_iters_MAXFREELIST 24 +# define Py_class_method_MAXFREELIST 10 # define Py_contexts_MAXFREELIST 255 # define Py_async_gens_MAXFREELIST 80 # define Py_async_gen_asends_MAXFREELIST 80 @@ -46,6 +47,7 @@ struct _Py_freelists { struct _Py_freelist slices; struct _Py_freelist ranges; struct _Py_freelist shared_iters; + struct _Py_freelist class_method; struct _Py_freelist contexts; struct _Py_freelist async_gens; struct _Py_freelist async_gen_asends; diff --git a/Objects/classobject.c b/Objects/classobject.c index 775894ad5a7166..408fcdab9e25b5 100644 --- a/Objects/classobject.c +++ b/Objects/classobject.c @@ -3,6 +3,7 @@ #include "Python.h" #include "pycore_call.h" // _PyObject_VectorcallTstate() #include "pycore_ceval.h" // _PyEval_GetBuiltin() +#include "pycore_freelist.h" #include "pycore_object.h" #include "pycore_pyerrors.h" #include "pycore_pystate.h" // _PyThreadState_GET() @@ -112,9 +113,13 @@ PyMethod_New(PyObject *func, PyObject *self) PyErr_BadInternalCall(); return NULL; } - PyMethodObject *im = PyObject_GC_New(PyMethodObject, &PyMethod_Type); + + PyMethodObject *im = _Py_FREELIST_POP(PyMethodObject, class_method); if (im == NULL) { - return NULL; + im = PyObject_GC_New(PyMethodObject, &PyMethod_Type); + if (im == NULL) { + return NULL; + } } im->im_weakreflist = NULL; im->im_func = Py_NewRef(func); @@ -245,7 +250,7 @@ method_dealloc(PyObject *self) PyObject_ClearWeakRefs((PyObject *)im); Py_DECREF(im->im_func); Py_XDECREF(im->im_self); - PyObject_GC_Del(im); + _Py_FREELIST_FREE(class_method, (PyObject *)im, PyObject_GC_Del); } static PyObject * diff --git a/Objects/iterobject.c b/Objects/iterobject.c index 135ced9ea1f268..3bd3a26968df5f 100644 --- a/Objects/iterobject.c +++ b/Objects/iterobject.c @@ -4,6 +4,7 @@ #include "pycore_abstract.h" // _PyObject_HasLen() #include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_ceval.h" // _PyEval_GetBuiltin() +#include "pycore_freelist.h" // _Py_FREELIST_PUSH(), _Py_FREELIST_POP() #include "pycore_object.h" // _PyObject_GC_TRACK() typedef struct { @@ -21,9 +22,16 @@ PySeqIter_New(PyObject *seq) PyErr_BadInternalCall(); return NULL; } - it = PyObject_GC_New(seqiterobject, &PySeqIter_Type); - if (it == NULL) - return NULL; + + it = _Py_FREELIST_POP(seqiterobject, shared_iters); + if (it == NULL) { + it = PyObject_GC_New(seqiterobject, &PySeqIter_Type); + if (it == NULL) + return NULL; + } + else { + Py_SET_TYPE(it, &PySeqIter_Type); + } it->it_index = 0; it->it_seq = Py_NewRef(seq); _PyObject_GC_TRACK(it); @@ -35,7 +43,8 @@ iter_dealloc(seqiterobject *it) { _PyObject_GC_UNTRACK(it); Py_XDECREF(it->it_seq); - PyObject_GC_Del(it); + assert(sizeof(seqiterobject)==sizeof(_PyListIterObject)); + _Py_FREELIST_FREE(shared_iters, (PyObject *)it, PyObject_GC_Del); } static int diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 4b4cf993395b9e..7f95b519561e68 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -6,7 +6,6 @@ #include "pycore_code.h" // CO_FAST_FREE #include "pycore_dict.h" // _PyDict_KeysSize() #include "pycore_frame.h" // _PyInterpreterFrame -#include "pycore_freelist.h" // _Py_FREELIST_FREE(), _Py_FREELIST_POP() #include "pycore_lock.h" // _PySeqLock_* #include "pycore_long.h" // _PyLong_IsNegative(), _PyLong_GetOne() #include "pycore_memoryobject.h" // _PyMemoryView_FromBufferProc() From 64be6c4ac1e02ca28029816d4f2fc2ee7d36318f Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Wed, 1 Jan 2025 20:16:20 +0100 Subject: [PATCH 6/9] clear freelists --- Objects/object.c | 3 +++ Objects/rangeobject.c | 1 + 2 files changed, 4 insertions(+) diff --git a/Objects/object.c b/Objects/object.c index d584414c559b9d..81df7dd41aa60f 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -937,6 +937,9 @@ _PyObject_ClearFreeLists(struct _Py_freelists *freelists, int is_finalization) } clear_freelist(&freelists->unicode_writers, is_finalization, PyMem_Free); clear_freelist(&freelists->ints, is_finalization, free_object); + clear_freelist(&freelists->shared_iters, is_finalization, free_object); + clear_freelist(&freelists->ranges, is_finalization, free_object); + clear_freelist(&freelists->class_method, is_finalization, free_object); } /* diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c index 529525e106b3c6..40916c641d4695 100644 --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -977,6 +977,7 @@ fast_range_iter(long start, long stop, long step, long len) } else { Py_SET_TYPE(it, &PyRangeIter_Type); + //_PyObject_GC_TRACK(it); // need to track with GC again } it->start = start; it->step = step; From 2551f2988b761ca8f84d64994ccbfb1c89d6c820 Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Wed, 1 Jan 2025 20:44:03 +0100 Subject: [PATCH 7/9] freelist for range iterators --- Include/internal/pycore_freelist_state.h | 2 ++ Objects/iterobject.c | 2 +- Objects/listobject.c | 2 +- Objects/object.c | 1 + Objects/rangeobject.c | 5 ++--- Objects/tupleobject.c | 2 +- 6 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Include/internal/pycore_freelist_state.h b/Include/internal/pycore_freelist_state.h index dfbb5105292642..dd5cc21cf45729 100644 --- a/Include/internal/pycore_freelist_state.h +++ b/Include/internal/pycore_freelist_state.h @@ -17,6 +17,7 @@ extern "C" { # define Py_ints_MAXFREELIST 100 # define Py_slices_MAXFREELIST 1 # define Py_ranges_MAXFREELIST 10 +# define Py_range_iters_MAXFREELIST 10 # define Py_shared_iters_MAXFREELIST 24 # define Py_class_method_MAXFREELIST 10 # define Py_contexts_MAXFREELIST 255 @@ -46,6 +47,7 @@ struct _Py_freelists { struct _Py_freelist dictkeys; struct _Py_freelist slices; struct _Py_freelist ranges; + struct _Py_freelist range_iters; struct _Py_freelist shared_iters; struct _Py_freelist class_method; struct _Py_freelist contexts; diff --git a/Objects/iterobject.c b/Objects/iterobject.c index 3bd3a26968df5f..de452092e90553 100644 --- a/Objects/iterobject.c +++ b/Objects/iterobject.c @@ -23,7 +23,7 @@ PySeqIter_New(PyObject *seq) return NULL; } - it = _Py_FREELIST_POP(seqiterobject, shared_iters); + it = 0; //_Py_FREELIST_POP(seqiterobject, shared_iters); if (it == NULL) { it = PyObject_GC_New(seqiterobject, &PySeqIter_Type); if (it == NULL) diff --git a/Objects/listobject.c b/Objects/listobject.c index c91ebe42a0f638..c72143655befef 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -3914,7 +3914,7 @@ list_iter(PyObject *seq) PyErr_BadInternalCall(); return NULL; } - _PyListIterObject *it = _Py_FREELIST_POP(_PyListIterObject, shared_iters); + _PyListIterObject *it = 0; //_Py_FREELIST_POP(_PyListIterObject, shared_iters); if (it == NULL) { it = PyObject_GC_New(_PyListIterObject, &PyListIter_Type); if (it == NULL) { diff --git a/Objects/object.c b/Objects/object.c index 81df7dd41aa60f..6ce38c4566f501 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -939,6 +939,7 @@ _PyObject_ClearFreeLists(struct _Py_freelists *freelists, int is_finalization) clear_freelist(&freelists->ints, is_finalization, free_object); clear_freelist(&freelists->shared_iters, is_finalization, free_object); clear_freelist(&freelists->ranges, is_finalization, free_object); + clear_freelist(&freelists->range_iters, is_finalization, free_object); clear_freelist(&freelists->class_method, is_finalization, free_object); } diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c index 40916c641d4695..a64522d19b7ded 100644 --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -886,7 +886,7 @@ rangeiter_setstate(_PyRangeIterObject *r, PyObject *state) static void rangeiter_dealloc(_PyRangeIterObject *r) { - _Py_FREELIST_FREE(shared_iters, r, PyObject_Free); + _Py_FREELIST_FREE(range_iters, r, PyObject_Free); } PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); @@ -969,7 +969,7 @@ 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 = _Py_FREELIST_POP(_PyRangeIterObject, shared_iters); + _PyRangeIterObject *it = _Py_FREELIST_POP(_PyRangeIterObject, range_iters); if (it == NULL) { it = PyObject_New(_PyRangeIterObject, &PyRangeIter_Type); if (it == NULL) @@ -977,7 +977,6 @@ fast_range_iter(long start, long stop, long step, long len) } else { Py_SET_TYPE(it, &PyRangeIter_Type); - //_PyObject_GC_TRACK(it); // need to track with GC again } it->start = start; it->step = step; diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index d2a18f8f7ac11b..0ae0a45a0737ed 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -1123,7 +1123,7 @@ tuple_iter(PyObject *seq) PyErr_BadInternalCall(); return NULL; } - it = _Py_FREELIST_POP(_PyTupleIterObject, shared_iters); + it = 0; // _Py_FREELIST_POP(_PyTupleIterObject, shared_iters); if (it == NULL) { it = PyObject_GC_New(_PyTupleIterObject, &PyTupleIter_Type); From fce4651fca7fa1d97ea5cdcce1baf97296375e67 Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Wed, 1 Jan 2025 21:10:28 +0100 Subject: [PATCH 8/9] enable all freelists again --- Objects/iterobject.c | 2 +- Objects/listobject.c | 2 +- Objects/tupleobject.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Objects/iterobject.c b/Objects/iterobject.c index de452092e90553..3bd3a26968df5f 100644 --- a/Objects/iterobject.c +++ b/Objects/iterobject.c @@ -23,7 +23,7 @@ PySeqIter_New(PyObject *seq) return NULL; } - it = 0; //_Py_FREELIST_POP(seqiterobject, shared_iters); + it = _Py_FREELIST_POP(seqiterobject, shared_iters); if (it == NULL) { it = PyObject_GC_New(seqiterobject, &PySeqIter_Type); if (it == NULL) diff --git a/Objects/listobject.c b/Objects/listobject.c index c72143655befef..c91ebe42a0f638 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -3914,7 +3914,7 @@ list_iter(PyObject *seq) PyErr_BadInternalCall(); return NULL; } - _PyListIterObject *it = 0; //_Py_FREELIST_POP(_PyListIterObject, shared_iters); + _PyListIterObject *it = _Py_FREELIST_POP(_PyListIterObject, shared_iters); if (it == NULL) { it = PyObject_GC_New(_PyListIterObject, &PyListIter_Type); if (it == NULL) { diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 0ae0a45a0737ed..d2a18f8f7ac11b 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -1123,7 +1123,7 @@ tuple_iter(PyObject *seq) PyErr_BadInternalCall(); return NULL; } - it = 0; // _Py_FREELIST_POP(_PyTupleIterObject, shared_iters); + it = _Py_FREELIST_POP(_PyTupleIterObject, shared_iters); if (it == NULL) { it = PyObject_GC_New(_PyTupleIterObject, &PyTupleIter_Type); From 5d13675cd8f2add3984ec7250e47120f93d4bd5b Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Wed, 1 Jan 2025 22:39:01 +0100 Subject: [PATCH 9/9] add PyCFunctionObject --- Include/internal/pycore_freelist_state.h | 4 ++++ Objects/methodobject.c | 26 +++++++++++++++++------- Objects/object.c | 2 ++ 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/Include/internal/pycore_freelist_state.h b/Include/internal/pycore_freelist_state.h index dd5cc21cf45729..5b95485a1ae63c 100644 --- a/Include/internal/pycore_freelist_state.h +++ b/Include/internal/pycore_freelist_state.h @@ -16,6 +16,8 @@ extern "C" { # define Py_floats_MAXFREELIST 100 # define Py_ints_MAXFREELIST 100 # define Py_slices_MAXFREELIST 1 +# define Py_pycfunctionobject_MAXFREELIST 40 +# define Py_pycmethodobject_MAXFREELIST 40 # define Py_ranges_MAXFREELIST 10 # define Py_range_iters_MAXFREELIST 10 # define Py_shared_iters_MAXFREELIST 24 @@ -46,6 +48,8 @@ struct _Py_freelists { struct _Py_freelist dicts; struct _Py_freelist dictkeys; struct _Py_freelist slices; + struct _Py_freelist pycfunctionobject; + struct _Py_freelist pycmethodobject; struct _Py_freelist ranges; struct _Py_freelist range_iters; struct _Py_freelist shared_iters; diff --git a/Objects/methodobject.c b/Objects/methodobject.c index 345da4607423cf..362b46c9b66b75 100644 --- a/Objects/methodobject.c +++ b/Objects/methodobject.c @@ -4,6 +4,7 @@ #include "Python.h" #include "pycore_call.h" // _Py_CheckFunctionResult() #include "pycore_ceval.h" // _Py_EnterRecursiveCallTstate() +#include "pycore_freelist.h" #include "pycore_object.h" #include "pycore_pyerrors.h" #include "pycore_pystate.h" // _PyThreadState_GET() @@ -85,10 +86,13 @@ PyCMethod_New(PyMethodDef *ml, PyObject *self, PyObject *module, PyTypeObject *c "flag but no class"); return NULL; } - PyCMethodObject *om = PyObject_GC_New(PyCMethodObject, &PyCMethod_Type); - if (om == NULL) { - return NULL; - } + PyCMethodObject *om = _Py_FREELIST_POP(PyCMethodObject, pycmethodobject); + if (om == NULL) { + om = PyObject_GC_New(PyCMethodObject, &PyCMethod_Type); + if (om == NULL) { + return NULL; + } + } om->mm_class = (PyTypeObject*)Py_NewRef(cls); op = (PyCFunctionObject *)om; } else { @@ -98,9 +102,12 @@ PyCMethod_New(PyMethodDef *ml, PyObject *self, PyObject *module, PyTypeObject *c "but no METH_METHOD flag"); return NULL; } - op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type); + op = _Py_FREELIST_POP(PyCFunctionObject, pycfunctionobject); if (op == NULL) { - return NULL; + op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type); + if (op == NULL) { + return NULL; + } } } @@ -171,7 +178,12 @@ meth_dealloc(PyObject *self) Py_XDECREF(PyCFunction_GET_CLASS(m)); Py_XDECREF(m->m_self); Py_XDECREF(m->m_module); - PyObject_GC_Del(m); + if (m->m_ml->ml_flags & METH_METHOD) { + _Py_FREELIST_FREE(pycmethodobject, m, PyObject_GC_Del); + } + else { + _Py_FREELIST_FREE(pycfunctionobject, m, PyObject_GC_Del); + } Py_TRASHCAN_END; } diff --git a/Objects/object.c b/Objects/object.c index 6ce38c4566f501..49be7628e04752 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -938,6 +938,8 @@ _PyObject_ClearFreeLists(struct _Py_freelists *freelists, int is_finalization) clear_freelist(&freelists->unicode_writers, is_finalization, PyMem_Free); clear_freelist(&freelists->ints, is_finalization, free_object); clear_freelist(&freelists->shared_iters, is_finalization, free_object); + clear_freelist(&freelists->pycfunctionobject, is_finalization, PyObject_GC_Del); + clear_freelist(&freelists->pycmethodobject, is_finalization, PyObject_GC_Del); clear_freelist(&freelists->ranges, is_finalization, free_object); clear_freelist(&freelists->range_iters, is_finalization, free_object); clear_freelist(&freelists->class_method, is_finalization, free_object); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy