diff options
author | Victor Stinner <vstinner@python.org> | 2020-06-04 21:38:36 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-04 21:38:36 (GMT) |
commit | 69ac6e58fd98de339c013fe64cd1cf763e4f9bca (patch) | |
tree | 98ab5b8f851d5512f097a73292e871a89c11f873 /Include/internal | |
parent | dc24b8a2ac32114313bae519db3ccc21fe45c982 (diff) | |
download | cpython-69ac6e58fd98de339c013fe64cd1cf763e4f9bca.zip cpython-69ac6e58fd98de339c013fe64cd1cf763e4f9bca.tar.gz cpython-69ac6e58fd98de339c013fe64cd1cf763e4f9bca.tar.bz2 |
bpo-40521: Make tuple free list per-interpreter (GH-20247)
Each interpreter now has its own tuple free lists:
* Move tuple numfree and free_list arrays into PyInterpreterState.
* Define PyTuple_MAXSAVESIZE and PyTuple_MAXFREELIST macros in
pycore_interp.h.
* Add _Py_tuple_state structure. Pass it explicitly to tuple_alloc().
* Add tstate parameter to _PyTuple_ClearFreeList()
* Each interpreter now has its own empty tuple singleton.
Diffstat (limited to 'Include/internal')
-rw-r--r-- | Include/internal/pycore_gc.h | 2 | ||||
-rw-r--r-- | Include/internal/pycore_interp.h | 21 | ||||
-rw-r--r-- | Include/internal/pycore_pylifecycle.h | 2 |
3 files changed, 23 insertions, 2 deletions
diff --git a/Include/internal/pycore_gc.h b/Include/internal/pycore_gc.h index 0511eea..e8e5d32 100644 --- a/Include/internal/pycore_gc.h +++ b/Include/internal/pycore_gc.h @@ -166,7 +166,7 @@ PyAPI_FUNC(void) _PyGC_InitState(struct _gc_runtime_state *); // Functions to clear types free lists extern void _PyFrame_ClearFreeList(void); -extern void _PyTuple_ClearFreeList(void); +extern void _PyTuple_ClearFreeList(PyThreadState *tstate); extern void _PyFloat_ClearFreeList(void); extern void _PyList_ClearFreeList(void); extern void _PyDict_ClearFreeList(void); diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index f04ea33..b90bfbe 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -64,6 +64,26 @@ struct _Py_unicode_state { struct _Py_unicode_fs_codec fs_codec; }; +/* Speed optimization to avoid frequent malloc/free of small tuples */ +#ifndef PyTuple_MAXSAVESIZE + // Largest tuple to save on free list +# define PyTuple_MAXSAVESIZE 20 +#endif +#ifndef PyTuple_MAXFREELIST + // Maximum number of tuples of each size to save +# define PyTuple_MAXFREELIST 2000 +#endif + +struct _Py_tuple_state { +#if PyTuple_MAXSAVESIZE > 0 + /* Entries 1 up to PyTuple_MAXSAVESIZE are free lists, + entry 0 is the empty tuple () of which at most one instance + will be allocated. */ + PyTupleObject *free_list[PyTuple_MAXSAVESIZE]; + int numfree[PyTuple_MAXSAVESIZE]; +#endif +}; + /* interpreter state */ @@ -157,6 +177,7 @@ struct _is { */ PyLongObject* small_ints[_PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS]; #endif + struct _Py_tuple_state tuple; }; /* Used by _PyImport_Cleanup() */ diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index 77ea3f2..3f2ff5b 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -60,7 +60,7 @@ extern PyStatus _PyGC_Init(PyThreadState *tstate); extern void _PyFrame_Fini(void); extern void _PyDict_Fini(void); -extern void _PyTuple_Fini(void); +extern void _PyTuple_Fini(PyThreadState *tstate); extern void _PyList_Fini(void); extern void _PySet_Fini(void); extern void _PyBytes_Fini(void); |