diff options
author | Victor Stinner <vstinner@python.org> | 2020-06-05 00:34:14 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-05 00:34:14 (GMT) |
commit | 78a02c2568714562e23e885b6dc5730601f35226 (patch) | |
tree | 167982aa5857ae92f0dd301aaa3e22e908a9d9a1 /Include | |
parent | 88ec9190105c9b03f49aaef601ce02b242a75273 (diff) | |
download | cpython-78a02c2568714562e23e885b6dc5730601f35226.zip cpython-78a02c2568714562e23e885b6dc5730601f35226.tar.gz cpython-78a02c2568714562e23e885b6dc5730601f35226.tar.bz2 |
bpo-40521: Make async gen free lists per-interpreter (GH-20643)
Each interpreter now has its own asynchronous generator free lists:
* Move async gen free lists into PyInterpreterState.
* Move _PyAsyncGen_MAXFREELIST define to pycore_interp.h
* Add _Py_async_gen_state structure.
* Add tstate parameter to _PyAsyncGen_ClearFreeLists
and _PyAsyncGen_Fini().
Diffstat (limited to 'Include')
-rw-r--r-- | Include/internal/pycore_gc.h | 2 | ||||
-rw-r--r-- | Include/internal/pycore_interp.h | 18 | ||||
-rw-r--r-- | Include/internal/pycore_pylifecycle.h | 2 |
3 files changed, 20 insertions, 2 deletions
diff --git a/Include/internal/pycore_gc.h b/Include/internal/pycore_gc.h index 3388b4d..ad2e552 100644 --- a/Include/internal/pycore_gc.h +++ b/Include/internal/pycore_gc.h @@ -170,7 +170,7 @@ extern void _PyTuple_ClearFreeList(PyThreadState *tstate); extern void _PyFloat_ClearFreeList(PyThreadState *tstate); extern void _PyList_ClearFreeList(PyThreadState *tstate); extern void _PyDict_ClearFreeList(void); -extern void _PyAsyncGen_ClearFreeLists(void); +extern void _PyAsyncGen_ClearFreeLists(PyThreadState *tstate); extern void _PyContext_ClearFreeList(void); #ifdef __cplusplus diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index 0eab246..d624218 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -108,6 +108,23 @@ struct _Py_frame_state { int numfree; }; +#ifndef _PyAsyncGen_MAXFREELIST +# define _PyAsyncGen_MAXFREELIST 80 +#endif + +struct _Py_async_gen_state { + /* Freelists boost performance 6-10%; they also reduce memory + fragmentation, as _PyAsyncGenWrappedValue and PyAsyncGenASend + are short-living objects that are instantiated for every + __anext__() call. */ + struct _PyAsyncGenWrappedValue* value_freelist[_PyAsyncGen_MAXFREELIST]; + int value_numfree; + + struct PyAsyncGenASend* asend_freelist[_PyAsyncGen_MAXFREELIST]; + int asend_numfree; +}; + + /* interpreter state */ @@ -205,6 +222,7 @@ struct _is { struct _Py_list_state list; struct _Py_float_state float_state; struct _Py_frame_state frame; + struct _Py_async_gen_state async_gen; /* Using a cache is very effective since typically only a single slice is created and then deleted again. */ diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index 3c35ca2..3e36573 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -66,7 +66,7 @@ extern void _PySet_Fini(void); extern void _PyBytes_Fini(void); extern void _PyFloat_Fini(PyThreadState *tstate); extern void _PySlice_Fini(PyThreadState *tstate); -extern void _PyAsyncGen_Fini(void); +extern void _PyAsyncGen_Fini(PyThreadState *tstate); extern void PyOS_FiniInterrupts(void); |