Skip to content

Commit c6e5c11

Browse files
authored
bpo-39489: Remove COUNT_ALLOCS special build (pythonGH-18259)
Remove: * COUNT_ALLOCS macro * sys.getcounts() function * SHOW_ALLOC_COUNT code in listobject.c * SHOW_TRACK_COUNT code in tupleobject.c * PyConfig.show_alloc_count field * -X showalloccount command line option * @test.support.requires_type_collecting decorator
1 parent 869c0c9 commit c6e5c11

34 files changed

+24
-469
lines changed

Doc/c-api/init_config.rst

+4-8
Original file line numberDiff line numberDiff line change
@@ -627,14 +627,6 @@ PyConfig
627627
628628
``python3 -m MODULE`` argument. Used by :c:func:`Py_RunMain`.
629629
630-
.. c:member:: int show_alloc_count
631-
632-
Show allocation counts at exit?
633-
634-
Set to 1 by :option:`-X showalloccount <-X>` command line option.
635-
636-
Need a special Python build with ``COUNT_ALLOCS`` macro defined.
637-
638630
.. c:member:: int show_ref_count
639631
640632
Show total reference count at exit?
@@ -702,6 +694,10 @@ arguments are stripped from ``argv``: see :ref:`Command Line Arguments
702694
The ``xoptions`` options are parsed to set other options: see :option:`-X`
703695
option.
704696
697+
.. versionchanged:: 3.9
698+
699+
The ``show_alloc_count`` field has been removed.
700+
705701
706702
Initialization with PyConfig
707703
----------------------------

Doc/c-api/typeobj.rst

-34
Original file line numberDiff line numberDiff line change
@@ -148,15 +148,6 @@ Quick Reference
148148
| :c:member:`~PyTypeObject.tp_vectorcall` | :c:type:`vectorcallfunc` | | | | | |
149149
+------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+
150150

151-
If :const:`COUNT_ALLOCS` is defined then the following (internal-only)
152-
fields exist as well:
153-
154-
* :c:member:`~PyTypeObject.tp_allocs`
155-
* :c:member:`~PyTypeObject.tp_frees`
156-
* :c:member:`~PyTypeObject.tp_maxalloc`
157-
* :c:member:`~PyTypeObject.tp_prev`
158-
* :c:member:`~PyTypeObject.tp_next`
159-
160151
.. [#slots]
161152
A slot name in parentheses indicates it is (effectively) deprecated.
162153
Names in angle brackets should be treated as read-only.
@@ -1904,31 +1895,6 @@ and :c:type:`PyType_Type` effectively act as defaults.)
19041895
.. versionadded:: 3.9 (the field exists since 3.8 but it's only used since 3.9)
19051896

19061897

1907-
The remaining fields are only defined if the feature test macro
1908-
:const:`COUNT_ALLOCS` is defined, and are for internal use only. They are
1909-
documented here for completeness. None of these fields are inherited by
1910-
subtypes.
1911-
1912-
.. c:member:: Py_ssize_t PyTypeObject.tp_allocs
1913-
1914-
Number of allocations.
1915-
1916-
.. c:member:: Py_ssize_t PyTypeObject.tp_frees
1917-
1918-
Number of frees.
1919-
1920-
.. c:member:: Py_ssize_t PyTypeObject.tp_maxalloc
1921-
1922-
Maximum simultaneously allocated objects.
1923-
1924-
.. c:member:: PyTypeObject* PyTypeObject.tp_prev
1925-
1926-
Pointer to the previous type object with a non-zero :c:member:`~PyTypeObject.tp_allocs` field.
1927-
1928-
.. c:member:: PyTypeObject* PyTypeObject.tp_next
1929-
1930-
Pointer to the next type object with a non-zero :c:member:`~PyTypeObject.tp_allocs` field.
1931-
19321898
Also, note that, in a garbage collected Python, :c:member:`~PyTypeObject.tp_dealloc` may be called from
19331899
any Python thread, not just the thread which created the object (if the object
19341900
becomes part of a refcount cycle, that cycle might be collected by a garbage

Doc/using/cmdline.rst

+2-3
Original file line numberDiff line numberDiff line change
@@ -434,9 +434,6 @@ Miscellaneous options
434434
stored in a traceback of a trace. Use ``-X tracemalloc=NFRAME`` to start
435435
tracing with a traceback limit of *NFRAME* frames. See the
436436
:func:`tracemalloc.start` for more information.
437-
* ``-X showalloccount`` to output the total count of allocated objects for
438-
each type when the program finishes. This only works when Python was built with
439-
``COUNT_ALLOCS`` defined.
440437
* ``-X importtime`` to show how long each import takes. It shows module
441438
name, cumulative time (including nested imports) and self time (excluding
442439
nested imports). Note that its output may be broken in multi-threaded
@@ -479,6 +476,8 @@ Miscellaneous options
479476
Using ``-X dev`` option, check *encoding* and *errors* arguments on
480477
string encoding and decoding operations.
481478

479+
The ``-X showalloccount`` option has been removed.
480+
482481

483482
Options you shouldn't use
484483
~~~~~~~~~~~~~~~~~~~~~~~~~

Doc/whatsnew/3.9.rst

+9
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,9 @@ Build and C API Changes
348348
functions are now required to build Python.
349349
(Contributed by Victor Stinner in :issue:`39395`.)
350350

351+
* The ``COUNT_ALLOCS`` special build macro has been removed.
352+
(Contributed by Victor Stinner in :issue:`39489`.)
353+
351354

352355
Deprecated
353356
==========
@@ -484,6 +487,12 @@ Removed
484487
``asyncio.Condition`` and ``asyncio.Semaphore``.
485488
(Contributed by Andrew Svetlov in :issue:`34793`.)
486489

490+
* The :func:`sys.getcounts` function, the ``-X showalloccount`` command line
491+
option and the ``show_alloc_count`` field of the C structure
492+
:c:type:`PyConfig` have been removed. They required a special Python build by
493+
defining ``COUNT_ALLOCS`` macro.
494+
(Contributed by Victor Stinner in :issue:`39489`.)
495+
487496

488497
Porting to Python 3.9
489498
=====================

Include/cpython/initconfig.h

-1
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,6 @@ typedef struct {
153153

154154
int import_time; /* PYTHONPROFILEIMPORTTIME, -X importtime */
155155
int show_ref_count; /* -X showrefcount */
156-
int show_alloc_count; /* -X showalloccount */
157156
int dump_refs; /* PYTHONDUMPREFS */
158157
int malloc_stats; /* PYTHONMALLOCSTATS */
159158

Include/cpython/object.h

-11
Original file line numberDiff line numberDiff line change
@@ -255,15 +255,6 @@ typedef struct _typeobject {
255255

256256
destructor tp_finalize;
257257
vectorcallfunc tp_vectorcall;
258-
259-
#ifdef COUNT_ALLOCS
260-
/* these must be last and never explicitly initialized */
261-
Py_ssize_t tp_allocs;
262-
Py_ssize_t tp_frees;
263-
Py_ssize_t tp_maxalloc;
264-
struct _typeobject *tp_prev;
265-
struct _typeobject *tp_next;
266-
#endif
267258
} PyTypeObject;
268259

269260
/* The *real* layout of a type object when allocated on the heap */
@@ -341,8 +332,6 @@ static inline void _Py_Dealloc_inline(PyObject *op)
341332
destructor dealloc = Py_TYPE(op)->tp_dealloc;
342333
#ifdef Py_TRACE_REFS
343334
_Py_ForgetReference(op);
344-
#else
345-
_Py_INC_TPFREES(op);
346335
#endif
347336
(*dealloc)(op);
348337
}

Include/object.h

+2-18
Original file line numberDiff line numberDiff line change
@@ -405,20 +405,6 @@ PyAPI_FUNC(void) _PyDebug_PrintTotalRefs(void);
405405
#define _Py_DEC_REFTOTAL
406406
#endif /* Py_REF_DEBUG */
407407

408-
#ifdef COUNT_ALLOCS
409-
PyAPI_FUNC(void) _Py_inc_count(struct _typeobject *);
410-
PyAPI_FUNC(void) _Py_dec_count(struct _typeobject *);
411-
#define _Py_INC_TPALLOCS(OP) _Py_inc_count(Py_TYPE(OP))
412-
#define _Py_INC_TPFREES(OP) _Py_dec_count(Py_TYPE(OP))
413-
#define _Py_DEC_TPFREES(OP) Py_TYPE(OP)->tp_frees--
414-
#define _Py_COUNT_ALLOCS_COMMA ,
415-
#else
416-
#define _Py_INC_TPALLOCS(OP)
417-
#define _Py_INC_TPFREES(OP)
418-
#define _Py_DEC_TPFREES(OP)
419-
#define _Py_COUNT_ALLOCS_COMMA
420-
#endif /* COUNT_ALLOCS */
421-
422408
/* Update the Python traceback of an object. This function must be called
423409
when a memory block is reused from a free list. */
424410
PyAPI_FUNC(int) _PyTraceMalloc_NewReference(PyObject *op);
@@ -438,15 +424,13 @@ static inline void _Py_NewReference(PyObject *op)
438424
if (_Py_tracemalloc_config.tracing) {
439425
_PyTraceMalloc_NewReference(op);
440426
}
441-
_Py_INC_TPALLOCS(op);
442427
_Py_INC_REFTOTAL;
443428
Py_REFCNT(op) = 1;
444429
}
445430

446-
static inline void _Py_ForgetReference(PyObject *op)
431+
static inline void _Py_ForgetReference(PyObject *Py_UNUSED(op))
447432
{
448-
(void)op; /* may be unused, shut up -Wunused-parameter */
449-
_Py_INC_TPFREES(op);
433+
/* nothing to do */
450434
}
451435
#endif /* !Py_TRACE_REFS */
452436

Lib/subprocess.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ def _args_from_interpreter_flags():
325325
if dev_mode:
326326
args.extend(('-X', 'dev'))
327327
for opt in ('faulthandler', 'tracemalloc', 'importtime',
328-
'showalloccount', 'showrefcount', 'utf8'):
328+
'showrefcount', 'utf8'):
329329
if opt in xoptions:
330330
value = xoptions[opt]
331331
if value is True:

Lib/test/support/__init__.py

-3
Original file line numberDiff line numberDiff line change
@@ -2512,9 +2512,6 @@ def swap_item(obj, item, new_val):
25122512
if item in obj:
25132513
del obj[item]
25142514

2515-
requires_type_collecting = unittest.skipIf(hasattr(sys, 'getcounts'),
2516-
'types are immortal if COUNT_ALLOCS is defined')
2517-
25182515
def args_from_interpreter_flags():
25192516
"""Return a list of command-line arguments reproducing the current
25202517
settings in sys.flags and sys.warnoptions."""

Lib/test/test_embed.py

-2
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,6 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
356356
'tracemalloc': 0,
357357
'import_time': 0,
358358
'show_ref_count': 0,
359-
'show_alloc_count': 0,
360359
'dump_refs': 0,
361360
'malloc_stats': 0,
362361

@@ -729,7 +728,6 @@ def test_init_from_config(self):
729728
'tracemalloc': 2,
730729
'import_time': 1,
731730
'show_ref_count': 1,
732-
'show_alloc_count': 1,
733731
'malloc_stats': 1,
734732

735733
'stdio_encoding': 'iso8859-1',

Lib/test/test_gc.py

+1-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import unittest.mock
33
from test.support import (verbose, refcount_test, run_unittest,
44
cpython_only, start_threads,
5-
temp_dir, requires_type_collecting, TESTFN, unlink,
5+
temp_dir, TESTFN, unlink,
66
import_module)
77
from test.support.script_helper import assert_python_ok, make_script
88

@@ -131,7 +131,6 @@ class A:
131131
del a
132132
self.assertNotEqual(gc.collect(), 0)
133133

134-
@requires_type_collecting
135134
def test_newinstance(self):
136135
class A(object):
137136
pass
@@ -709,7 +708,6 @@ def run_command(code):
709708
stderr = run_command(code % "gc.DEBUG_SAVEALL")
710709
self.assertNotIn(b"uncollectable objects at shutdown", stderr)
711710

712-
@requires_type_collecting
713711
def test_gc_main_module_at_shutdown(self):
714712
# Create a reference cycle through the __main__ module and check
715713
# it gets collected at interpreter shutdown.
@@ -723,7 +721,6 @@ def __del__(self):
723721
rc, out, err = assert_python_ok('-c', code)
724722
self.assertEqual(out.strip(), b'__del__ called')
725723

726-
@requires_type_collecting
727724
def test_gc_ordinary_module_at_shutdown(self):
728725
# Same as above, but with a non-__main__ module.
729726
with temp_dir() as script_dir:
@@ -743,7 +740,6 @@ def __del__(self):
743740
rc, out, err = assert_python_ok('-c', code)
744741
self.assertEqual(out.strip(), b'__del__ called')
745742

746-
@requires_type_collecting
747743
def test_global_del_SystemExit(self):
748744
code = """if 1:
749745
class ClassWithDel:

Lib/test/test_io.py

-2
Original file line numberDiff line numberDiff line change
@@ -3492,7 +3492,6 @@ def __del__(self):
34923492
""".format(iomod=iomod, kwargs=kwargs)
34933493
return assert_python_ok("-c", code)
34943494

3495-
@support.requires_type_collecting
34963495
def test_create_at_shutdown_without_encoding(self):
34973496
rc, out, err = self._check_create_at_shutdown()
34983497
if err:
@@ -3502,7 +3501,6 @@ def test_create_at_shutdown_without_encoding(self):
35023501
else:
35033502
self.assertEqual("ok", out.decode().strip())
35043503

3505-
@support.requires_type_collecting
35063504
def test_create_at_shutdown_with_encoding(self):
35073505
rc, out, err = self._check_create_at_shutdown(encoding='utf-8',
35083506
errors='strict')

Lib/test/test_logging.py

-1
Original file line numberDiff line numberDiff line change
@@ -4252,7 +4252,6 @@ def __init__(self, name='MyLogger', level=logging.NOTSET):
42524252
h.close()
42534253
logging.setLoggerClass(logging.Logger)
42544254

4255-
@support.requires_type_collecting
42564255
def test_logging_at_shutdown(self):
42574256
# Issue #20037
42584257
code = """if 1:

Lib/test/test_module.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Test the module type
22
import unittest
33
import weakref
4-
from test.support import gc_collect, requires_type_collecting
4+
from test.support import gc_collect
55
from test.support.script_helper import assert_python_ok
66

77
import sys
@@ -101,7 +101,6 @@ def f():
101101
gc_collect()
102102
self.assertEqual(f().__dict__["bar"], 4)
103103

104-
@requires_type_collecting
105104
def test_clear_dict_in_ref_cycle(self):
106105
destroyed = []
107106
m = ModuleType("foo")
@@ -266,7 +265,6 @@ def test_module_repr_source(self):
266265
self.assertEqual(r[-len(ends_with):], ends_with,
267266
'{!r} does not end with {!r}'.format(r, ends_with))
268267

269-
@requires_type_collecting
270268
def test_module_finalization_at_shutdown(self):
271269
# Module globals and builtins should still be available during shutdown
272270
rc, out, err = assert_python_ok("-c", "from test import final_a")

Lib/test/test_support.py

-1
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,6 @@ def test_args_from_interpreter_flags(self):
493493
['-Wignore', '-X', 'dev'],
494494
['-X', 'faulthandler'],
495495
['-X', 'importtime'],
496-
['-X', 'showalloccount'],
497496
['-X', 'showrefcount'],
498497
['-X', 'tracemalloc'],
499498
['-X', 'tracemalloc=3'],

Lib/test/test_sys.py

-4
Original file line numberDiff line numberDiff line change
@@ -819,7 +819,6 @@ def test_getallocatedblocks(self):
819819
c = sys.getallocatedblocks()
820820
self.assertIn(c, range(b - 50, b + 50))
821821

822-
@test.support.requires_type_collecting
823822
def test_is_finalizing(self):
824823
self.assertIs(sys.is_finalizing(), False)
825824
# Don't use the atexit module because _Py_Finalizing is only set
@@ -841,7 +840,6 @@ def __del__(self):
841840
rc, stdout, stderr = assert_python_ok('-c', code)
842841
self.assertEqual(stdout.rstrip(), b'True')
843842

844-
@test.support.requires_type_collecting
845843
def test_issue20602(self):
846844
# sys.flags and sys.float_info were wiped during shutdown.
847845
code = """if 1:
@@ -1295,8 +1293,6 @@ def delx(self): del self.__x
12951293
# type
12961294
# static type: PyTypeObject
12971295
fmt = 'P2nPI13Pl4Pn9Pn11PIPP'
1298-
if hasattr(sys, 'getcounts'):
1299-
fmt += '3n2P'
13001296
s = vsize(fmt)
13011297
check(int, s)
13021298
# class

Lib/test/test_threading.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
"""
44

55
import test.support
6-
from test.support import (verbose, import_module, cpython_only,
7-
requires_type_collecting)
6+
from test.support import verbose, import_module, cpython_only
87
from test.support.script_helper import assert_python_ok, assert_python_failure
98

109
import random
@@ -552,7 +551,6 @@ def f():
552551
self.assertEqual(err, b"")
553552
self.assertEqual(data, "Thread-1\nTrue\nTrue\n")
554553

555-
@requires_type_collecting
556554
def test_main_thread_during_shutdown(self):
557555
# bpo-31516: current_thread() should still point to the main thread
558556
# at shutdown
@@ -1113,7 +1111,6 @@ def run():
11131111
self.assertIn("ZeroDivisionError", err)
11141112
self.assertNotIn("Unhandled exception", err)
11151113

1116-
@requires_type_collecting
11171114
def test_print_exception_stderr_is_none_1(self):
11181115
script = r"""if True:
11191116
import sys

Lib/test/test_traceback.py

-1
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,6 @@ def do_test(firstlines, message, charset, lineno):
174174
# Issue #18960: coding spec should have no effect
175175
do_test("x=0\n# coding: GBK\n", "h\xe9 ho", 'utf-8', 5)
176176

177-
@support.requires_type_collecting
178177
def test_print_traceback_at_exit(self):
179178
# Issue #22599: Ensure that it is possible to use the traceback module
180179
# to display an exception at Python exit

Lib/test/test_warnings/__init__.py

-1
Original file line numberDiff line numberDiff line change
@@ -1227,7 +1227,6 @@ def test_issue_8766(self):
12271227

12281228

12291229
class FinalizationTest(unittest.TestCase):
1230-
@support.requires_type_collecting
12311230
def test_finalization(self):
12321231
# Issue #19421: warnings.warn() should not crash
12331232
# during Python finalization

Lib/test/test_weakref.py

-1
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,6 @@ class D:
649649
del c1, c2, C, D
650650
gc.collect()
651651

652-
@support.requires_type_collecting
653652
def test_callback_in_cycle_resurrection(self):
654653
import gc
655654

Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Remove ``COUNT_ALLOCS`` special build.

0 commit comments

Comments
 (0)