diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index d839893d2c657e..9bdee425b0b5c8 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -31,6 +31,10 @@ def requires_subinterpreters(meth): return unittest.skipIf(interpreters is None, 'subinterpreters required')(meth) +class ObjectWithValue: + value: ObjectWithValue | None + def __init__(self, value): + self.value = value DICT_KEY_STRUCT_FORMAT = 'n2BI2n' @@ -1475,6 +1479,16 @@ def test_gc_head_size(self): # but lists are self.assertEqual(sys.getsizeof([]), vsize('Pn') + gc_header_size) + def test_inline_values(self): + vsize = test.support.calcvobjsize + gc_header_size = self.gc_headsize + inline_values_size = vsize('P') + + linked_list = None + for i in range(28): + linked_list = ObjectWithValue(linked_list) + self.assertEqual(sys.getsizeof(linked_list), vsize('P') + gc_header_size + inline_values_size) + def test_errors(self): class BadSizeof: def __sizeof__(self): diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-12-13-38-23.gh-issue-128762.O3iYBW.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-12-13-38-23.gh-issue-128762.O3iYBW.rst new file mode 100644 index 00000000000000..b9f8932c11f3b9 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-12-13-38-23.gh-issue-128762.O3iYBW.rst @@ -0,0 +1 @@ +:func:`sys.getsizeof` now accounts for inline values stored alongside the object diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 887591a681b25c..451f24bf6f8523 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1842,10 +1842,11 @@ _PySys_GetSizeOf(PyObject *o) PyObject *res = NULL; PyObject *method; Py_ssize_t size; + PyTypeObject *type = Py_TYPE(o); PyThreadState *tstate = _PyThreadState_GET(); /* Make sure the type is initialized. float gets initialized late */ - if (PyType_Ready(Py_TYPE(o)) < 0) { + if (PyType_Ready(type) < 0) { return (size_t)-1; } @@ -1854,7 +1855,7 @@ _PySys_GetSizeOf(PyObject *o) if (!_PyErr_Occurred(tstate)) { _PyErr_Format(tstate, PyExc_TypeError, "Type %.100s doesn't define __sizeof__", - Py_TYPE(o)->tp_name); + type->tp_name); } } else { @@ -1876,6 +1877,10 @@ _PySys_GetSizeOf(PyObject *o) return (size_t)-1; } + if (type->tp_flags & Py_TPFLAGS_INLINE_VALUES) { + size += _PyInlineValuesSize(type); + } + size_t presize = 0; if (!Py_IS_TYPE(o, &PyType_Type) || PyType_HasFeature((PyTypeObject *)o, Py_TPFLAGS_HEAPTYPE))