changeset: 76530:b044e0568be2 user: Martin v. Loewis date: Tue Apr 24 19:13:57 2012 +0200 files: Include/dictobject.h Lib/test/test_sys.py Objects/dictobject.c Objects/typeobject.c description: Account for shared keys in type's __sizeof__ (#13903). diff -r 6f41f8ed87c8 -r b044e0568be2 Include/dictobject.h --- a/Include/dictobject.h Tue Apr 24 18:39:53 2012 +0200 +++ b/Include/dictobject.h Tue Apr 24 19:13:57 2012 +0200 @@ -75,6 +75,7 @@ PyAPI_FUNC(PyObject *) _PyDict_NewPresized(Py_ssize_t minused); PyAPI_FUNC(void) _PyDict_MaybeUntrack(PyObject *mp); PyAPI_FUNC(int) _PyDict_HasOnlyStringKeys(PyObject *mp); +Py_ssize_t _PyDict_KeysSize(PyDictKeysObject *keys); #define _PyDict_HasSplitTable(d) ((d)->ma_values != NULL) PyAPI_FUNC(int) PyDict_ClearFreeList(void); diff -r 6f41f8ed87c8 -r b044e0568be2 Lib/test/test_sys.py --- a/Lib/test/test_sys.py Tue Apr 24 18:39:53 2012 +0200 +++ b/Lib/test/test_sys.py Tue Apr 24 19:13:57 2012 +0200 @@ -829,13 +829,19 @@ check((), size(vh)) check((1,2,3), size(vh) + 3*self.P) # type + # static type: PyTypeObject + s = size(vh + 'P2P15Pl4PP9PP11PI') + check(int, s) # (PyTypeObject + PyNumberMethods + PyMappingMethods + - # PySequenceMethods + PyBufferProcs) - s = size(vh + 'P2P15Pl4PP9PP11PIP') + size('16Pi17P 3P 10P 2P 3P') - check(int, s) + # PySequenceMethods + PyBufferProcs + 4P) + s = size(vh + 'P2P15Pl4PP9PP11PI') + size('34P 3P 10P 2P 4P') + # Separate block for PyDictKeysObject with 4 entries + s += size("PPPP") + 4*size("PPP") # class class newstyleclass(object): pass check(newstyleclass, s) + # dict with shared keys + check(newstyleclass().__dict__, size(h+"PPP4P")) # unicode # each tuple contains a string and its expected character size # don't put any static strings here, as they may contain diff -r 6f41f8ed87c8 -r b044e0568be2 Objects/dictobject.c --- a/Objects/dictobject.c Tue Apr 24 18:39:53 2012 +0200 +++ b/Objects/dictobject.c Tue Apr 24 19:13:57 2012 +0200 @@ -2398,22 +2398,23 @@ static PyObject * dict_sizeof(PyDictObject *mp) { - Py_ssize_t size; - double res, keys_size; + Py_ssize_t size, res; size = DK_SIZE(mp->ma_keys); res = sizeof(PyDictObject); if (mp->ma_values) res += size * sizeof(PyObject*); - /* Count our share of the keys object -- with rounding errors. */ - keys_size = sizeof(PyDictKeysObject) + (size-1) * sizeof(PyDictKeyEntry); - /* If refcnt> 1, then one count is (probably) held by a type */ - /* XXX This is somewhat approximate :) */ - if (mp->ma_keys->dk_refcnt < 3) - res += keys_size; - else - res += keys_size / (mp->ma_keys->dk_refcnt - 1); - return PyFloat_FromDouble(res); + /* If the dictionary is split, the keys portion is accounted-for + in the type object. */ + if (mp->ma_keys->dk_refcnt == 1) + res += sizeof(PyDictKeysObject) + (size-1) * sizeof(PyDictKeyEntry); + return PyLong_FromSsize_t(res); +} + +Py_ssize_t +_PyDict_KeysSize(PyDictKeysObject *keys) +{ + return sizeof(PyDictKeysObject) + (DK_SIZE(keys)-1) * sizeof(PyDictKeyEntry); } PyDoc_STRVAR(contains__doc__, diff -r 6f41f8ed87c8 -r b044e0568be2 Objects/typeobject.c --- a/Objects/typeobject.c Tue Apr 24 18:39:53 2012 +0200 +++ b/Objects/typeobject.c Tue Apr 24 19:13:57 2012 +0200 @@ -2730,6 +2730,22 @@ return result; } +static PyObject* +type_sizeof(PyObject *self, PyObject *args_unused) +{ + Py_ssize_t size; + PyTypeObject *type = (PyTypeObject*)self; + if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) { + PyHeapTypeObject* et = (PyHeapTypeObject*)type; + size = sizeof(PyHeapTypeObject); + if (et->ht_cached_keys) + size += _PyDict_KeysSize(et->ht_cached_keys); + } + else + size = sizeof(PyTypeObject); + return PyLong_FromSsize_t(size); +} + static PyMethodDef type_methods[] = { {"mro", (PyCFunction)mro_external, METH_NOARGS, PyDoc_STR("mro() -> list\nreturn a type's method resolution order")}, @@ -2745,6 +2761,8 @@ PyDoc_STR("__subclasscheck__() -> bool\ncheck if a class is a subclass")}, {"__dir__", type_dir, METH_NOARGS, PyDoc_STR("__dir__() -> list\nspecialized __dir__ implementation for types")}, + {"__sizeof__", type_sizeof, METH_NOARGS, + "__sizeof__() -> int\nreturn memory consumption of the type object"}, {0} };

AltStyle によって変換されたページ (->オリジナル) /