From ad7c7785461fffba04f5a36cd6d062e92b0fda16 Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Mon, 23 Sep 2024 18:28:59 -0700 Subject: [PATCH] gh-123990: Good bye WITH_FREELISTS macro (gh-124358) --- Doc/using/configure.rst | 6 ----- Doc/whatsnew/3.11.rst | 2 +- Include/internal/pycore_freelist.h | 8 ------ Include/internal/pycore_freelist_state.h | 9 ------- Lib/test/pythoninfo.py | 1 - Lib/test/test_sys.py | 6 +---- ...-09-23-11-27-25.gh-issue-123990.d6HrYC.rst | 1 + Objects/dictobject.c | 2 -- Objects/floatobject.c | 9 +------ Objects/listobject.c | 2 -- Objects/object.c | 5 ---- Objects/tupleobject.c | 2 -- PC/pyconfig.h.in | 3 --- configure | 27 ------------------- configure.ac | 18 ------------- pyconfig.h.in | 3 --- 16 files changed, 4 insertions(+), 100 deletions(-) create mode 100644 Misc/NEWS.d/next/Build/2024-09-23-11-27-25.gh-issue-123990.d6HrYC.rst diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index 10adf744c7ff52..4976418ba33cf8 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -183,12 +183,6 @@ General Options 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 Python library directory name (default is ``lib``). diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index d59f24406c9483..e5c6d7cd308504 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -2168,7 +2168,7 @@ Build Changes (Contributed by Donghee Na and Brett Holman in :issue:`44340`.) * 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. (Contributed by Christian Heimes in :issue:`45522`.) diff --git a/Include/internal/pycore_freelist.h b/Include/internal/pycore_freelist.h index 1ac0fed584ebd9..da2d7bf6ae1393 100644 --- a/Include/internal/pycore_freelist.h +++ b/Include/internal/pycore_freelist.h @@ -28,13 +28,6 @@ _Py_freelists_GET(void) #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 #define _Py_FREELIST_FREE(NAME, op, freefunc) \ _PyFreeList_Free(&_Py_freelists_GET()->NAME, _PyObject_CAST(op), \ @@ -108,7 +101,6 @@ _PyFreeList_PopMem(struct _Py_freelist *fl) } return op; } -#endif extern void _PyObject_ClearFreeLists(struct _Py_freelists *freelists, int is_finalization); diff --git a/Include/internal/pycore_freelist_state.h b/Include/internal/pycore_freelist_state.h index e8df784bcba06e..762c583ce94e9a 100644 --- a/Include/internal/pycore_freelist_state.h +++ b/Include/internal/pycore_freelist_state.h @@ -8,8 +8,6 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#ifdef WITH_FREELISTS -// with freelists # 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_lists_MAXFREELIST 80 @@ -22,9 +20,6 @@ extern "C" { # define Py_async_gen_asends_MAXFREELIST 80 # define Py_futureiters_MAXFREELIST 255 # define Py_object_stack_chunks_MAXFREELIST 4 -#else -# define PyTuple_MAXSAVESIZE 0 -#endif // A generic freelist of either PyObjects or other data structures. struct _Py_freelist { @@ -38,7 +33,6 @@ struct _Py_freelist { }; struct _Py_freelists { -#ifdef WITH_FREELISTS struct _Py_freelist floats; struct _Py_freelist tuples[PyTuple_MAXSAVESIZE]; struct _Py_freelist lists; @@ -50,9 +44,6 @@ struct _Py_freelists { struct _Py_freelist async_gen_asends; struct _Py_freelist futureiters; struct _Py_freelist object_stack_chunks; -#else - char _unused; // Empty structs are not allowed. -#endif }; #ifdef __cplusplus diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py index d928e002ebda10..05a28bda2d38ba 100644 --- a/Lib/test/pythoninfo.py +++ b/Lib/test/pythoninfo.py @@ -553,7 +553,6 @@ def collect_sysconfig(info_add): for name in ( 'WITH_DOC_STRINGS', 'WITH_DTRACE', - 'WITH_FREELISTS', 'WITH_MIMALLOC', 'WITH_PYMALLOC', 'WITH_VALGRIND', diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 77009648bd26ed..9689ef8e96e072 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1042,14 +1042,10 @@ def test_debugmallocstats(self): # Output of sys._debugmallocstats() depends on configure flags. # The sysconfig vars are not available on Windows. if sys.platform != "win32": - with_freelists = sysconfig.get_config_var("WITH_FREELISTS") 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: self.assertIn(b'Small block threshold', err) - if not with_freelists and not with_pymalloc: - self.assertFalse(err) # The function has no parameter self.assertRaises(TypeError, sys._debugmallocstats, True) diff --git a/Misc/NEWS.d/next/Build/2024-09-23-11-27-25.gh-issue-123990.d6HrYC.rst b/Misc/NEWS.d/next/Build/2024-09-23-11-27-25.gh-issue-123990.d6HrYC.rst new file mode 100644 index 00000000000000..2b4f993323297a --- /dev/null +++ b/Misc/NEWS.d/next/Build/2024-09-23-11-27-25.gh-issue-123990.d6HrYC.rst @@ -0,0 +1 @@ +Remove ``WITH_FREELISTS`` macro and ``--without-freelists`` build configuration diff --git a/Objects/dictobject.c b/Objects/dictobject.c index db21961bad266b..f38ab1b2865e99 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -406,14 +406,12 @@ unicode_get_hash(PyObject *o) void _PyDict_DebugMallocStats(FILE *out) { -#ifdef WITH_FREELISTS _PyDebugAllocatorStats(out, "free PyDictObject", _Py_FREELIST_SIZE(dicts), sizeof(PyDictObject)); _PyDebugAllocatorStats(out, "free PyDictKeysObject", _Py_FREELIST_SIZE(dictkeys), sizeof(PyDictKeysObject)); -#endif } #define DK_MASK(dk) (DK_SIZE(dk)-1) diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 68fd3e54632950..dc3d8a3e5d0f4b 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -235,15 +235,10 @@ static void float_dealloc(PyObject *op) { assert(PyFloat_Check(op)); -#ifdef WITH_FREELISTS - if (PyFloat_CheckExact(op)) { + if (PyFloat_CheckExact(op)) _PyFloat_ExactDealloc(op); - } else -#endif - { Py_TYPE(op)->tp_free(op); - } } double @@ -1975,12 +1970,10 @@ _PyFloat_FiniType(PyInterpreterState *interp) void _PyFloat_DebugMallocStats(FILE *out) { -#ifdef WITH_FREELISTS _PyDebugAllocatorStats(out, "free PyFloatObject", _Py_FREELIST_SIZE(floats), sizeof(PyFloatObject)); -#endif } diff --git a/Objects/listobject.c b/Objects/listobject.c index 067d1a18d3bb75..8abe15d6674140 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -200,12 +200,10 @@ list_preallocate_exact(PyListObject *self, Py_ssize_t size) void _PyList_DebugMallocStats(FILE *out) { -#ifdef WITH_FREELISTS _PyDebugAllocatorStats(out, "free PyListObject", _Py_FREELIST_SIZE(lists), sizeof(PyListObject)); -#endif } PyObject * diff --git a/Objects/object.c b/Objects/object.c index 4b8b6c29266812..bc63b8120a5160 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -816,7 +816,6 @@ PyObject_Bytes(PyObject *v) return PyBytes_FromObject(v); } -#ifdef WITH_FREELISTS static void clear_freelist(struct _Py_freelist *freelist, int is_finalization, freefunc dofree) @@ -841,12 +840,9 @@ free_object(void *obj) Py_DECREF(tp); } -#endif - void _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 default build, freelists are per-interpreter and cleared in finalize_interp_types() 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. clear_freelist(&freelists->object_stack_chunks, 1, PyMem_RawFree); } -#endif } /* diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index bd6e568191167a..f14f10ab9c0a46 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -1146,7 +1146,6 @@ maybe_freelist_push(PyTupleObject *op) void _PyTuple_DebugMallocStats(FILE *out) { -#ifdef WITH_FREELISTS for (int i = 0; i < PyTuple_MAXSAVESIZE; i++) { int len = i + 1; char buf[128]; @@ -1155,5 +1154,4 @@ _PyTuple_DebugMallocStats(FILE *out) _PyDebugAllocatorStats(out, buf, _Py_FREELIST_SIZE(tuples[i]), _PyObject_VAR_SIZE(&PyTuple_Type, len)); } -#endif } diff --git a/PC/pyconfig.h.in b/PC/pyconfig.h.in index f44e41c2e72f84..503f3193e2803e 100644 --- a/PC/pyconfig.h.in +++ b/PC/pyconfig.h.in @@ -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 WITH_MIMALLOC 1 -/* Define if you want to compile in object freelists optimization */ -#define WITH_FREELISTS 1 - /* Define if you have clock. */ /* #define HAVE_CLOCK */ diff --git a/configure b/configure index 56b923b764ec46..0cc73e4e66552d 100755 --- a/configure +++ b/configure @@ -1116,7 +1116,6 @@ enable_ipv6 with_doc_strings with_mimalloc with_pymalloc -with_freelists with_c_locale_coercion with_valgrind with_dtrace @@ -1918,7 +1917,6 @@ Optional Packages: --with-mimalloc build with mimalloc memory allocator (default is yes if C11 stdatomic.h is available.) --with-pymalloc enable specialized mallocs (default is yes) - --with-freelists enable object freelists (default is yes) --with-c-locale-coercion enable C locale coercion to a UTF-8 based locale (default is yes) @@ -17979,31 +17977,6 @@ fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_pymalloc" >&5 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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for --with-c-locale-coercion" >&5 printf %s "checking for --with-c-locale-coercion... " >&6; } diff --git a/configure.ac b/configure.ac index c4df726cd6a8ae..1864e94ace9243 100644 --- a/configure.ac +++ b/configure.ac @@ -4977,24 +4977,6 @@ then fi 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 AC_MSG_CHECKING([for --with-c-locale-coercion]) AC_ARG_WITH( diff --git a/pyconfig.h.in b/pyconfig.h.in index a5946f3547b35c..7f02603e26f5d0 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -1901,9 +1901,6 @@ /* Define to build the readline module against libedit. */ #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. */ #undef WITH_LIBINTL