mirror of https://github.com/python/cpython.git
gh-123990: Good bye WITH_FREELISTS macro (gh-124358)
This commit is contained in:
parent
be76e3f26e
commit
ad7c778546
|
@ -183,12 +183,6 @@ General Options
|
||||||
|
|
||||||
See :envvar:`PYTHONCOERCECLOCALE` and the :pep:`538`.
|
See :envvar:`PYTHONCOERCECLOCALE` and the :pep:`538`.
|
||||||
|
|
||||||
.. option:: --without-freelists
|
|
||||||
|
|
||||||
Disable all freelists except the empty tuple singleton.
|
|
||||||
|
|
||||||
.. versionadded:: 3.11
|
|
||||||
|
|
||||||
.. option:: --with-platlibdir=DIRNAME
|
.. option:: --with-platlibdir=DIRNAME
|
||||||
|
|
||||||
Python library directory name (default is ``lib``).
|
Python library directory name (default is ``lib``).
|
||||||
|
|
|
@ -2168,7 +2168,7 @@ Build Changes
|
||||||
(Contributed by Donghee Na and Brett Holman in :issue:`44340`.)
|
(Contributed by Donghee Na and Brett Holman in :issue:`44340`.)
|
||||||
|
|
||||||
* Freelists for object structs can now be disabled. A new :program:`configure`
|
* Freelists for object structs can now be disabled. A new :program:`configure`
|
||||||
option :option:`--without-freelists` can be used to disable all freelists
|
option ``--without-freelists`` can be used to disable all freelists
|
||||||
except empty tuple singleton.
|
except empty tuple singleton.
|
||||||
(Contributed by Christian Heimes in :issue:`45522`.)
|
(Contributed by Christian Heimes in :issue:`45522`.)
|
||||||
|
|
||||||
|
|
|
@ -28,13 +28,6 @@ _Py_freelists_GET(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef WITH_FREELISTS
|
|
||||||
#define _Py_FREELIST_FREE(NAME, op, freefunc) freefunc(op)
|
|
||||||
#define _Py_FREELIST_PUSH(NAME, op, limit) (0)
|
|
||||||
#define _Py_FREELIST_POP(TYPE, NAME) (NULL)
|
|
||||||
#define _Py_FREELIST_POP_MEM(NAME) (NULL)
|
|
||||||
#define _Py_FREELIST_SIZE(NAME) (0)
|
|
||||||
#else
|
|
||||||
// Pushes `op` to the freelist, calls `freefunc` if the freelist is full
|
// Pushes `op` to the freelist, calls `freefunc` if the freelist is full
|
||||||
#define _Py_FREELIST_FREE(NAME, op, freefunc) \
|
#define _Py_FREELIST_FREE(NAME, op, freefunc) \
|
||||||
_PyFreeList_Free(&_Py_freelists_GET()->NAME, _PyObject_CAST(op), \
|
_PyFreeList_Free(&_Py_freelists_GET()->NAME, _PyObject_CAST(op), \
|
||||||
|
@ -108,7 +101,6 @@ _PyFreeList_PopMem(struct _Py_freelist *fl)
|
||||||
}
|
}
|
||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
extern void _PyObject_ClearFreeLists(struct _Py_freelists *freelists, int is_finalization);
|
extern void _PyObject_ClearFreeLists(struct _Py_freelists *freelists, int is_finalization);
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,6 @@ extern "C" {
|
||||||
# error "this header requires Py_BUILD_CORE define"
|
# error "this header requires Py_BUILD_CORE define"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_FREELISTS
|
|
||||||
// with freelists
|
|
||||||
# define PyTuple_MAXSAVESIZE 20 // Largest tuple to save on freelist
|
# define PyTuple_MAXSAVESIZE 20 // Largest tuple to save on freelist
|
||||||
# define Py_tuple_MAXFREELIST 2000 // Maximum number of tuples of each size to save
|
# define Py_tuple_MAXFREELIST 2000 // Maximum number of tuples of each size to save
|
||||||
# define Py_lists_MAXFREELIST 80
|
# define Py_lists_MAXFREELIST 80
|
||||||
|
@ -22,9 +20,6 @@ extern "C" {
|
||||||
# define Py_async_gen_asends_MAXFREELIST 80
|
# define Py_async_gen_asends_MAXFREELIST 80
|
||||||
# define Py_futureiters_MAXFREELIST 255
|
# define Py_futureiters_MAXFREELIST 255
|
||||||
# define Py_object_stack_chunks_MAXFREELIST 4
|
# define Py_object_stack_chunks_MAXFREELIST 4
|
||||||
#else
|
|
||||||
# define PyTuple_MAXSAVESIZE 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// A generic freelist of either PyObjects or other data structures.
|
// A generic freelist of either PyObjects or other data structures.
|
||||||
struct _Py_freelist {
|
struct _Py_freelist {
|
||||||
|
@ -38,7 +33,6 @@ struct _Py_freelist {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _Py_freelists {
|
struct _Py_freelists {
|
||||||
#ifdef WITH_FREELISTS
|
|
||||||
struct _Py_freelist floats;
|
struct _Py_freelist floats;
|
||||||
struct _Py_freelist tuples[PyTuple_MAXSAVESIZE];
|
struct _Py_freelist tuples[PyTuple_MAXSAVESIZE];
|
||||||
struct _Py_freelist lists;
|
struct _Py_freelist lists;
|
||||||
|
@ -50,9 +44,6 @@ struct _Py_freelists {
|
||||||
struct _Py_freelist async_gen_asends;
|
struct _Py_freelist async_gen_asends;
|
||||||
struct _Py_freelist futureiters;
|
struct _Py_freelist futureiters;
|
||||||
struct _Py_freelist object_stack_chunks;
|
struct _Py_freelist object_stack_chunks;
|
||||||
#else
|
|
||||||
char _unused; // Empty structs are not allowed.
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -553,7 +553,6 @@ def collect_sysconfig(info_add):
|
||||||
for name in (
|
for name in (
|
||||||
'WITH_DOC_STRINGS',
|
'WITH_DOC_STRINGS',
|
||||||
'WITH_DTRACE',
|
'WITH_DTRACE',
|
||||||
'WITH_FREELISTS',
|
|
||||||
'WITH_MIMALLOC',
|
'WITH_MIMALLOC',
|
||||||
'WITH_PYMALLOC',
|
'WITH_PYMALLOC',
|
||||||
'WITH_VALGRIND',
|
'WITH_VALGRIND',
|
||||||
|
|
|
@ -1042,14 +1042,10 @@ def test_debugmallocstats(self):
|
||||||
# Output of sys._debugmallocstats() depends on configure flags.
|
# Output of sys._debugmallocstats() depends on configure flags.
|
||||||
# The sysconfig vars are not available on Windows.
|
# The sysconfig vars are not available on Windows.
|
||||||
if sys.platform != "win32":
|
if sys.platform != "win32":
|
||||||
with_freelists = sysconfig.get_config_var("WITH_FREELISTS")
|
|
||||||
with_pymalloc = sysconfig.get_config_var("WITH_PYMALLOC")
|
with_pymalloc = sysconfig.get_config_var("WITH_PYMALLOC")
|
||||||
if with_freelists:
|
|
||||||
self.assertIn(b"free PyDictObjects", err)
|
self.assertIn(b"free PyDictObjects", err)
|
||||||
if with_pymalloc:
|
if with_pymalloc:
|
||||||
self.assertIn(b'Small block threshold', err)
|
self.assertIn(b'Small block threshold', err)
|
||||||
if not with_freelists and not with_pymalloc:
|
|
||||||
self.assertFalse(err)
|
|
||||||
|
|
||||||
# The function has no parameter
|
# The function has no parameter
|
||||||
self.assertRaises(TypeError, sys._debugmallocstats, True)
|
self.assertRaises(TypeError, sys._debugmallocstats, True)
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Remove ``WITH_FREELISTS`` macro and ``--without-freelists`` build configuration
|
|
@ -406,14 +406,12 @@ unicode_get_hash(PyObject *o)
|
||||||
void
|
void
|
||||||
_PyDict_DebugMallocStats(FILE *out)
|
_PyDict_DebugMallocStats(FILE *out)
|
||||||
{
|
{
|
||||||
#ifdef WITH_FREELISTS
|
|
||||||
_PyDebugAllocatorStats(out, "free PyDictObject",
|
_PyDebugAllocatorStats(out, "free PyDictObject",
|
||||||
_Py_FREELIST_SIZE(dicts),
|
_Py_FREELIST_SIZE(dicts),
|
||||||
sizeof(PyDictObject));
|
sizeof(PyDictObject));
|
||||||
_PyDebugAllocatorStats(out, "free PyDictKeysObject",
|
_PyDebugAllocatorStats(out, "free PyDictKeysObject",
|
||||||
_Py_FREELIST_SIZE(dictkeys),
|
_Py_FREELIST_SIZE(dictkeys),
|
||||||
sizeof(PyDictKeysObject));
|
sizeof(PyDictKeysObject));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DK_MASK(dk) (DK_SIZE(dk)-1)
|
#define DK_MASK(dk) (DK_SIZE(dk)-1)
|
||||||
|
|
|
@ -235,15 +235,10 @@ static void
|
||||||
float_dealloc(PyObject *op)
|
float_dealloc(PyObject *op)
|
||||||
{
|
{
|
||||||
assert(PyFloat_Check(op));
|
assert(PyFloat_Check(op));
|
||||||
#ifdef WITH_FREELISTS
|
if (PyFloat_CheckExact(op))
|
||||||
if (PyFloat_CheckExact(op)) {
|
|
||||||
_PyFloat_ExactDealloc(op);
|
_PyFloat_ExactDealloc(op);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
#endif
|
|
||||||
{
|
|
||||||
Py_TYPE(op)->tp_free(op);
|
Py_TYPE(op)->tp_free(op);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double
|
double
|
||||||
|
@ -1975,12 +1970,10 @@ _PyFloat_FiniType(PyInterpreterState *interp)
|
||||||
void
|
void
|
||||||
_PyFloat_DebugMallocStats(FILE *out)
|
_PyFloat_DebugMallocStats(FILE *out)
|
||||||
{
|
{
|
||||||
#ifdef WITH_FREELISTS
|
|
||||||
_PyDebugAllocatorStats(out,
|
_PyDebugAllocatorStats(out,
|
||||||
"free PyFloatObject",
|
"free PyFloatObject",
|
||||||
_Py_FREELIST_SIZE(floats),
|
_Py_FREELIST_SIZE(floats),
|
||||||
sizeof(PyFloatObject));
|
sizeof(PyFloatObject));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -200,12 +200,10 @@ list_preallocate_exact(PyListObject *self, Py_ssize_t size)
|
||||||
void
|
void
|
||||||
_PyList_DebugMallocStats(FILE *out)
|
_PyList_DebugMallocStats(FILE *out)
|
||||||
{
|
{
|
||||||
#ifdef WITH_FREELISTS
|
|
||||||
_PyDebugAllocatorStats(out,
|
_PyDebugAllocatorStats(out,
|
||||||
"free PyListObject",
|
"free PyListObject",
|
||||||
_Py_FREELIST_SIZE(lists),
|
_Py_FREELIST_SIZE(lists),
|
||||||
sizeof(PyListObject));
|
sizeof(PyListObject));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
|
|
|
@ -816,7 +816,6 @@ PyObject_Bytes(PyObject *v)
|
||||||
return PyBytes_FromObject(v);
|
return PyBytes_FromObject(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_FREELISTS
|
|
||||||
static void
|
static void
|
||||||
clear_freelist(struct _Py_freelist *freelist, int is_finalization,
|
clear_freelist(struct _Py_freelist *freelist, int is_finalization,
|
||||||
freefunc dofree)
|
freefunc dofree)
|
||||||
|
@ -841,12 +840,9 @@ free_object(void *obj)
|
||||||
Py_DECREF(tp);
|
Py_DECREF(tp);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_PyObject_ClearFreeLists(struct _Py_freelists *freelists, int is_finalization)
|
_PyObject_ClearFreeLists(struct _Py_freelists *freelists, int is_finalization)
|
||||||
{
|
{
|
||||||
#ifdef WITH_FREELISTS
|
|
||||||
// In the free-threaded build, freelists are per-PyThreadState and cleared in PyThreadState_Clear()
|
// In the free-threaded build, freelists are per-PyThreadState and cleared in PyThreadState_Clear()
|
||||||
// In the default build, freelists are per-interpreter and cleared in finalize_interp_types()
|
// In the default build, freelists are per-interpreter and cleared in finalize_interp_types()
|
||||||
clear_freelist(&freelists->floats, is_finalization, free_object);
|
clear_freelist(&freelists->floats, is_finalization, free_object);
|
||||||
|
@ -866,7 +862,6 @@ _PyObject_ClearFreeLists(struct _Py_freelists *freelists, int is_finalization)
|
||||||
// stacks during GC, so emptying the free-list is counterproductive.
|
// stacks during GC, so emptying the free-list is counterproductive.
|
||||||
clear_freelist(&freelists->object_stack_chunks, 1, PyMem_RawFree);
|
clear_freelist(&freelists->object_stack_chunks, 1, PyMem_RawFree);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1146,7 +1146,6 @@ maybe_freelist_push(PyTupleObject *op)
|
||||||
void
|
void
|
||||||
_PyTuple_DebugMallocStats(FILE *out)
|
_PyTuple_DebugMallocStats(FILE *out)
|
||||||
{
|
{
|
||||||
#ifdef WITH_FREELISTS
|
|
||||||
for (int i = 0; i < PyTuple_MAXSAVESIZE; i++) {
|
for (int i = 0; i < PyTuple_MAXSAVESIZE; i++) {
|
||||||
int len = i + 1;
|
int len = i + 1;
|
||||||
char buf[128];
|
char buf[128];
|
||||||
|
@ -1155,5 +1154,4 @@ _PyTuple_DebugMallocStats(FILE *out)
|
||||||
_PyDebugAllocatorStats(out, buf, _Py_FREELIST_SIZE(tuples[i]),
|
_PyDebugAllocatorStats(out, buf, _Py_FREELIST_SIZE(tuples[i]),
|
||||||
_PyObject_VAR_SIZE(&PyTuple_Type, len));
|
_PyObject_VAR_SIZE(&PyTuple_Type, len));
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -531,9 +531,6 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */
|
||||||
/* Define if you want to compile in mimalloc memory allocator. */
|
/* Define if you want to compile in mimalloc memory allocator. */
|
||||||
#define WITH_MIMALLOC 1
|
#define WITH_MIMALLOC 1
|
||||||
|
|
||||||
/* Define if you want to compile in object freelists optimization */
|
|
||||||
#define WITH_FREELISTS 1
|
|
||||||
|
|
||||||
/* Define if you have clock. */
|
/* Define if you have clock. */
|
||||||
/* #define HAVE_CLOCK */
|
/* #define HAVE_CLOCK */
|
||||||
|
|
||||||
|
|
|
@ -1116,7 +1116,6 @@ enable_ipv6
|
||||||
with_doc_strings
|
with_doc_strings
|
||||||
with_mimalloc
|
with_mimalloc
|
||||||
with_pymalloc
|
with_pymalloc
|
||||||
with_freelists
|
|
||||||
with_c_locale_coercion
|
with_c_locale_coercion
|
||||||
with_valgrind
|
with_valgrind
|
||||||
with_dtrace
|
with_dtrace
|
||||||
|
@ -1918,7 +1917,6 @@ Optional Packages:
|
||||||
--with-mimalloc build with mimalloc memory allocator (default is yes
|
--with-mimalloc build with mimalloc memory allocator (default is yes
|
||||||
if C11 stdatomic.h is available.)
|
if C11 stdatomic.h is available.)
|
||||||
--with-pymalloc enable specialized mallocs (default is yes)
|
--with-pymalloc enable specialized mallocs (default is yes)
|
||||||
--with-freelists enable object freelists (default is yes)
|
|
||||||
--with-c-locale-coercion
|
--with-c-locale-coercion
|
||||||
enable C locale coercion to a UTF-8 based locale
|
enable C locale coercion to a UTF-8 based locale
|
||||||
(default is yes)
|
(default is yes)
|
||||||
|
@ -17979,31 +17977,6 @@ fi
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_pymalloc" >&5
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_pymalloc" >&5
|
||||||
printf "%s\n" "$with_pymalloc" >&6; }
|
printf "%s\n" "$with_pymalloc" >&6; }
|
||||||
|
|
||||||
# Check whether objects such as float, tuple and dict are using
|
|
||||||
# freelists to optimization memory allocation.
|
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for --with-freelists" >&5
|
|
||||||
printf %s "checking for --with-freelists... " >&6; }
|
|
||||||
|
|
||||||
# Check whether --with-freelists was given.
|
|
||||||
if test ${with_freelists+y}
|
|
||||||
then :
|
|
||||||
withval=$with_freelists;
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
if test -z "$with_freelists"
|
|
||||||
then
|
|
||||||
with_freelists="yes"
|
|
||||||
fi
|
|
||||||
if test "$with_freelists" != "no"
|
|
||||||
then
|
|
||||||
|
|
||||||
printf "%s\n" "#define WITH_FREELISTS 1" >>confdefs.h
|
|
||||||
|
|
||||||
fi
|
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_freelists" >&5
|
|
||||||
printf "%s\n" "$with_freelists" >&6; }
|
|
||||||
|
|
||||||
# Check for --with-c-locale-coercion
|
# Check for --with-c-locale-coercion
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for --with-c-locale-coercion" >&5
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for --with-c-locale-coercion" >&5
|
||||||
printf %s "checking for --with-c-locale-coercion... " >&6; }
|
printf %s "checking for --with-c-locale-coercion... " >&6; }
|
||||||
|
|
18
configure.ac
18
configure.ac
|
@ -4977,24 +4977,6 @@ then
|
||||||
fi
|
fi
|
||||||
AC_MSG_RESULT([$with_pymalloc])
|
AC_MSG_RESULT([$with_pymalloc])
|
||||||
|
|
||||||
# Check whether objects such as float, tuple and dict are using
|
|
||||||
# freelists to optimization memory allocation.
|
|
||||||
AC_MSG_CHECKING([for --with-freelists])
|
|
||||||
AC_ARG_WITH(
|
|
||||||
[freelists],
|
|
||||||
[AS_HELP_STRING([--with-freelists], [enable object freelists (default is yes)])])
|
|
||||||
|
|
||||||
if test -z "$with_freelists"
|
|
||||||
then
|
|
||||||
with_freelists="yes"
|
|
||||||
fi
|
|
||||||
if test "$with_freelists" != "no"
|
|
||||||
then
|
|
||||||
AC_DEFINE([WITH_FREELISTS], [1],
|
|
||||||
[Define if you want to compile in object freelists optimization])
|
|
||||||
fi
|
|
||||||
AC_MSG_RESULT([$with_freelists])
|
|
||||||
|
|
||||||
# Check for --with-c-locale-coercion
|
# Check for --with-c-locale-coercion
|
||||||
AC_MSG_CHECKING([for --with-c-locale-coercion])
|
AC_MSG_CHECKING([for --with-c-locale-coercion])
|
||||||
AC_ARG_WITH(
|
AC_ARG_WITH(
|
||||||
|
|
|
@ -1901,9 +1901,6 @@
|
||||||
/* Define to build the readline module against libedit. */
|
/* Define to build the readline module against libedit. */
|
||||||
#undef WITH_EDITLINE
|
#undef WITH_EDITLINE
|
||||||
|
|
||||||
/* Define if you want to compile in object freelists optimization */
|
|
||||||
#undef WITH_FREELISTS
|
|
||||||
|
|
||||||
/* Define to 1 if libintl is needed for locale functions. */
|
/* Define to 1 if libintl is needed for locale functions. */
|
||||||
#undef WITH_LIBINTL
|
#undef WITH_LIBINTL
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue