diff options
author | Donghee Na <donghee.na@python.org> | 2024-01-11 18:46:28 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-11 18:46:28 (GMT) |
commit | 2e7577b622616ef5ff2d1460fb5bebf845f0edf3 (patch) | |
tree | 3972f8fc6ea93e3eed72284df76d1d710cca896f /Include | |
parent | 8717f7b495c8c33fd37017f4e7684609c304c556 (diff) | |
download | cpython-2e7577b622616ef5ff2d1460fb5bebf845f0edf3.zip cpython-2e7577b622616ef5ff2d1460fb5bebf845f0edf3.tar.gz cpython-2e7577b622616ef5ff2d1460fb5bebf845f0edf3.tar.bz2 |
gh-111968: Use per-thread freelists for tuple in free-threading (gh-113921)
Diffstat (limited to 'Include')
-rw-r--r-- | Include/internal/pycore_freelist.h | 26 | ||||
-rw-r--r-- | Include/internal/pycore_gc.h | 2 | ||||
-rw-r--r-- | Include/internal/pycore_tuple.h | 45 |
3 files changed, 28 insertions, 45 deletions
diff --git a/Include/internal/pycore_freelist.h b/Include/internal/pycore_freelist.h index d41153d..3400943 100644 --- a/Include/internal/pycore_freelist.h +++ b/Include/internal/pycore_freelist.h @@ -8,11 +8,19 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif +// PyTuple_MAXSAVESIZE - largest tuple to save on free list +// PyTuple_MAXFREELIST - maximum number of tuples of each size to save + #ifdef WITH_FREELISTS // with freelists +# define PyTuple_MAXSAVESIZE 20 +# define PyTuple_NFREELISTS PyTuple_MAXSAVESIZE +# define PyTuple_MAXFREELIST 2000 # define PyList_MAXFREELIST 80 # define PyFloat_MAXFREELIST 100 #else +# define PyTuple_NFREELISTS 0 +# define PyTuple_MAXFREELIST 0 # define PyList_MAXFREELIST 0 # define PyFloat_MAXFREELIST 0 #endif @@ -24,6 +32,23 @@ struct _Py_list_state { #endif }; +struct _Py_tuple_state { +#if WITH_FREELISTS + /* There is one freelist for each size from 1 to PyTuple_MAXSAVESIZE. + The empty tuple is handled separately. + + Each tuple stored in the array is the head of the linked list + (and the next available tuple) for that size. The actual tuple + object is used as the linked list node, with its first item + (ob_item[0]) pointing to the next node (i.e. the previous head). + Each linked list is initially NULL. */ + PyTupleObject *free_list[PyTuple_NFREELISTS]; + int numfree[PyTuple_NFREELISTS]; +#else + char _unused; // Empty structs are not allowed. +#endif +}; + struct _Py_float_state { #ifdef WITH_FREELISTS /* Special free list @@ -36,6 +61,7 @@ struct _Py_float_state { typedef struct _Py_freelist_state { struct _Py_float_state float_state; + struct _Py_tuple_state tuple_state; struct _Py_list_state list_state; } _PyFreeListState; diff --git a/Include/internal/pycore_gc.h b/Include/internal/pycore_gc.h index 753763a..c029b23 100644 --- a/Include/internal/pycore_gc.h +++ b/Include/internal/pycore_gc.h @@ -246,7 +246,7 @@ extern PyObject *_PyGC_GetReferrers(PyInterpreterState *interp, PyObject *objs); // Functions to clear types free lists extern void _PyGC_ClearAllFreeLists(PyInterpreterState *interp); extern void _Py_ClearFreeLists(_PyFreeListState *state, int is_finalization); -extern void _PyTuple_ClearFreeList(PyInterpreterState *interp); +extern void _PyTuple_ClearFreeList(_PyFreeListState *state, int is_finalization); extern void _PyFloat_ClearFreeList(_PyFreeListState *state, int is_finalization); extern void _PyList_ClearFreeList(_PyFreeListState *state, int is_finalization); extern void _PyDict_ClearFreeList(PyInterpreterState *interp); diff --git a/Include/internal/pycore_tuple.h b/Include/internal/pycore_tuple.h index 4fa7a12..b348339 100644 --- a/Include/internal/pycore_tuple.h +++ b/Include/internal/pycore_tuple.h @@ -14,59 +14,16 @@ extern void _PyTuple_DebugMallocStats(FILE *out); /* runtime lifecycle */ extern PyStatus _PyTuple_InitGlobalObjects(PyInterpreterState *); -extern void _PyTuple_Fini(PyInterpreterState *); +extern void _PyTuple_Fini(_PyFreeListState *); /* other API */ -// PyTuple_MAXSAVESIZE - largest tuple to save on free list -// PyTuple_MAXFREELIST - maximum number of tuples of each size to save - -#if defined(PyTuple_MAXSAVESIZE) && PyTuple_MAXSAVESIZE <= 0 - // A build indicated that tuple freelists should not be used. -# define PyTuple_NFREELISTS 0 -# undef PyTuple_MAXSAVESIZE -# undef PyTuple_MAXFREELIST - -#elif !defined(WITH_FREELISTS) -# define PyTuple_NFREELISTS 0 -# undef PyTuple_MAXSAVESIZE -# undef PyTuple_MAXFREELIST - -#else - // We are using a freelist for tuples. -# ifndef PyTuple_MAXSAVESIZE -# define PyTuple_MAXSAVESIZE 20 -# endif -# define PyTuple_NFREELISTS PyTuple_MAXSAVESIZE -# ifndef PyTuple_MAXFREELIST -# define PyTuple_MAXFREELIST 2000 -# endif -#endif - -struct _Py_tuple_state { -#if PyTuple_NFREELISTS > 0 - /* There is one freelist for each size from 1 to PyTuple_MAXSAVESIZE. - The empty tuple is handled separately. - - Each tuple stored in the array is the head of the linked list - (and the next available tuple) for that size. The actual tuple - object is used as the linked list node, with its first item - (ob_item[0]) pointing to the next node (i.e. the previous head). - Each linked list is initially NULL. */ - PyTupleObject *free_list[PyTuple_NFREELISTS]; - int numfree[PyTuple_NFREELISTS]; -#else - char _unused; // Empty structs are not allowed. -#endif -}; - #define _PyTuple_ITEMS(op) _Py_RVALUE(_PyTuple_CAST(op)->ob_item) extern PyObject *_PyTuple_FromArray(PyObject *const *, Py_ssize_t); extern PyObject *_PyTuple_FromArraySteal(PyObject *const *, Py_ssize_t); - typedef struct { PyObject_HEAD Py_ssize_t it_index; |