bpo-45522: Allow to disable freelists on build time (GH-29056)

Freelists for object structs can now be disabled. A new ``configure``
option ``--without-freelists`` can be used to disable all freelists
except empty tuple singleton. Internal Py*_MAXFREELIST macros can now
be defined as 0 without causing compiler warnings and segfaults.

Signed-off-by: Christian Heimes <christian@python.org>
This commit is contained in:
Christian Heimes 2021-10-21 16:12:20 +03:00 committed by GitHub
parent 5a14f71fe8
commit 9942f42a93
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 218 additions and 35 deletions

View file

@ -85,12 +85,31 @@ struct _Py_unicode_state {
struct _Py_unicode_ids ids;
};
#ifndef WITH_FREELISTS
// without freelists
# define PyFloat_MAXFREELIST 0
// for tuples only store empty tuple singleton
# define PyTuple_MAXSAVESIZE 1
# define PyTuple_MAXFREELIST 1
# define PyList_MAXFREELIST 0
# define PyDict_MAXFREELIST 0
# define PyFrame_MAXFREELIST 0
# define _PyAsyncGen_MAXFREELIST 0
# define PyContext_MAXFREELIST 0
#endif
#ifndef PyFloat_MAXFREELIST
# define PyFloat_MAXFREELIST 100
#endif
struct _Py_float_state {
#if PyFloat_MAXFREELIST > 0
/* Special free list
free_list is a singly-linked list of available PyFloatObjects,
linked via abuse of their ob_type members. */
int numfree;
PyFloatObject *free_list;
#endif
};
/* Speed optimization to avoid frequent malloc/free of small tuples */
@ -119,8 +138,10 @@ struct _Py_tuple_state {
#endif
struct _Py_list_state {
#if PyList_MAXFREELIST > 0
PyListObject *free_list[PyList_MAXFREELIST];
int numfree;
#endif
};
#ifndef PyDict_MAXFREELIST
@ -128,17 +149,25 @@ struct _Py_list_state {
#endif
struct _Py_dict_state {
#if PyDict_MAXFREELIST > 0
/* Dictionary reuse scheme to save calls to malloc and free */
PyDictObject *free_list[PyDict_MAXFREELIST];
int numfree;
PyDictKeysObject *keys_free_list[PyDict_MAXFREELIST];
int keys_numfree;
#endif
};
#ifndef PyFrame_MAXFREELIST
# define PyFrame_MAXFREELIST 200
#endif
struct _Py_frame_state {
#if PyFrame_MAXFREELIST > 0
PyFrameObject *free_list;
/* number of frames currently in free_list */
int numfree;
#endif
};
#ifndef _PyAsyncGen_MAXFREELIST
@ -146,6 +175,7 @@ struct _Py_frame_state {
#endif
struct _Py_async_gen_state {
#if _PyAsyncGen_MAXFREELIST > 0
/* Freelists boost performance 6-10%; they also reduce memory
fragmentation, as _PyAsyncGenWrappedValue and PyAsyncGenASend
are short-living objects that are instantiated for every
@ -155,12 +185,19 @@ struct _Py_async_gen_state {
struct PyAsyncGenASend* asend_freelist[_PyAsyncGen_MAXFREELIST];
int asend_numfree;
#endif
};
#ifndef PyContext_MAXFREELIST
# define PyContext_MAXFREELIST 255
#endif
struct _Py_context_state {
#if PyContext_MAXFREELIST > 0
// List of free PyContext objects
PyContext *freelist;
int numfree;
#endif
};
struct _Py_exc_state {