From 9cbbb47ecfaa4b0a6fde326984535335771ed4ef Mon Sep 17 00:00:00 2001 From: Josh Snyder Date: Sun, 12 Jan 2025 13:35:22 -0800 Subject: [PATCH 1/5] Include inline values in sys.getsizeof --- Lib/test/test_sys.py | 14 ++++++++++++++ Python/sysmodule.c | 9 +++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index d839893d2c657e..b4b5b9a4a3a425 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 = 32 + + 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/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)) From 9efb00d3d7d165f91427f6f0fc12117a547222af Mon Sep 17 00:00:00 2001 From: Josh Snyder Date: Sun, 12 Jan 2025 13:38:43 -0800 Subject: [PATCH 2/5] add NEWS entry --- .../2025-01-12-13-38-23.gh-issue-128762.O3iYBW.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-01-12-13-38-23.gh-issue-128762.O3iYBW.rst 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..bf7988ab495536 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-12-13-38-23.gh-issue-128762.O3iYBW.rst @@ -0,0 +1 @@ +`sys.getsizeof()` now accounts for inline values stored alongside the object From 1baca2d51992ef66c43c0a4c8a56abbe647109db Mon Sep 17 00:00:00 2001 From: Josh Snyder Date: Sun, 12 Jan 2025 13:45:12 -0800 Subject: [PATCH 3/5] fix news --- .../2025-01-12-13-38-23.gh-issue-128762.O3iYBW.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index bf7988ab495536..b9f8932c11f3b9 100644 --- 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 @@ -1 +1 @@ -`sys.getsizeof()` now accounts for inline values stored alongside the object +:func:`sys.getsizeof` now accounts for inline values stored alongside the object From 17e43a3a6767d269a284c154a77fc668f718d7e5 Mon Sep 17 00:00:00 2001 From: Josh Snyder Date: Sun, 12 Jan 2025 14:53:24 -0800 Subject: [PATCH 4/5] fix 32-bit tests --- Lib/test/test_sys.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index b4b5b9a4a3a425..51b85c6cd71d90 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1482,7 +1482,7 @@ def test_gc_head_size(self): def test_inline_values(self): vsize = test.support.calcvobjsize gc_header_size = self.gc_headsize - inline_values_size = 32 + inline_values_size = vsize('PP') linked_list = None for i in range(28): From 368313c4ac5eee024873e17812887617c97b009b Mon Sep 17 00:00:00 2001 From: Josh Snyder Date: Sun, 12 Jan 2025 16:28:38 -0800 Subject: [PATCH 5/5] try again --- Lib/test/test_sys.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 51b85c6cd71d90..9bdee425b0b5c8 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1482,7 +1482,7 @@ def test_gc_head_size(self): def test_inline_values(self): vsize = test.support.calcvobjsize gc_header_size = self.gc_headsize - inline_values_size = vsize('PP') + inline_values_size = vsize('P') linked_list = None for i in range(28):