Commit 68f87329 authored by Robert Schuppenies's avatar Robert Schuppenies

Merged revisions 64842,64853,64856,64945 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r64842 | robert.schuppenies | 2008-07-10 15:43:26 +0200 (Thu, 10 Jul 2008) | 2 lines

  Fixed Issue3122 and extended sys.getsizeof tests for built-in types.
........
  r64853 | robert.schuppenies | 2008-07-10 17:24:04 +0200 (Thu, 10 Jul 2008) | 3 lines

  Added additional __sizeof__ implementations and addressed comments made in
  Issue3122.
........
  r64856 | robert.schuppenies | 2008-07-10 19:13:55 +0200 (Thu, 10 Jul 2008) | 3 lines

  Added garbage collector overhead and optional default return value to
  sys.getsizeof.
........
  r64945 | robert.schuppenies | 2008-07-14 10:42:18 +0200 (Mon, 14 Jul 2008) | 2 lines

  Fixed test failure on Win64 machines.
........
parent 5d5463a5
...@@ -331,13 +331,20 @@ always available. ...@@ -331,13 +331,20 @@ always available.
:func:`setrecursionlimit`. :func:`setrecursionlimit`.
.. function:: getsizeof(object) .. function:: getsizeof(object[, default])
Return the size of an object in bytes. The object can be any type of Return the size of an object in bytes. The object can be any type of
object. All built-in objects will return correct results, but this object. All built-in objects will return correct results, but this
does not have to hold true for third-party extensions as it is implementation does not have to hold true for third-party extensions as it is implementation
specific. specific.
The *default* argument allows to define a value which will be returned
if the object type does not provide means to retrieve the size and would
cause a `TypeError`.
func:`getsizeof` calls the object's __sizeof__ method and adds an additional
garbage collector overhead if the object is managed by the garbage collector.
.. versionadded:: 2.6 .. versionadded:: 2.6
......
This diff is collapsed.
...@@ -1182,6 +1182,7 @@ PyInit__testcapi(void) ...@@ -1182,6 +1182,7 @@ PyInit__testcapi(void)
PyModule_AddObject(m, "ULLONG_MAX", PyLong_FromUnsignedLongLong(PY_ULLONG_MAX)); PyModule_AddObject(m, "ULLONG_MAX", PyLong_FromUnsignedLongLong(PY_ULLONG_MAX));
PyModule_AddObject(m, "PY_SSIZE_T_MAX", PyLong_FromSsize_t(PY_SSIZE_T_MAX)); PyModule_AddObject(m, "PY_SSIZE_T_MAX", PyLong_FromSsize_t(PY_SSIZE_T_MAX));
PyModule_AddObject(m, "PY_SSIZE_T_MIN", PyLong_FromSsize_t(PY_SSIZE_T_MIN)); PyModule_AddObject(m, "PY_SSIZE_T_MIN", PyLong_FromSsize_t(PY_SSIZE_T_MIN));
PyModule_AddObject(m, "SIZEOF_PYGC_HEAD", PyLong_FromSsize_t(sizeof(PyGC_Head)));
TestError = PyErr_NewException("_testcapi.error", NULL, NULL); TestError = PyErr_NewException("_testcapi.error", NULL, NULL);
Py_INCREF(TestError); Py_INCREF(TestError);
......
...@@ -3033,6 +3033,19 @@ bytes_reduce(PyByteArrayObject *self) ...@@ -3033,6 +3033,19 @@ bytes_reduce(PyByteArrayObject *self)
return Py_BuildValue("(O(Ns)N)", Py_TYPE(self), latin1, "latin-1", dict); return Py_BuildValue("(O(Ns)N)", Py_TYPE(self), latin1, "latin-1", dict);
} }
PyDoc_STRVAR(sizeof_doc,
"B.__sizeof__() -> int\n\
\n\
Returns the size of B in memory, in bytes");
static PyObject *
bytes_sizeof(PyByteArrayObject *self)
{
Py_ssize_t res;
res = sizeof(PyByteArrayObject) + self->ob_alloc * sizeof(char);
return PyLong_FromSsize_t(res);
}
static PySequenceMethods bytes_as_sequence = { static PySequenceMethods bytes_as_sequence = {
(lenfunc)bytes_length, /* sq_length */ (lenfunc)bytes_length, /* sq_length */
(binaryfunc)PyByteArray_Concat, /* sq_concat */ (binaryfunc)PyByteArray_Concat, /* sq_concat */
...@@ -3061,6 +3074,7 @@ static PyMethodDef ...@@ -3061,6 +3074,7 @@ static PyMethodDef
bytes_methods[] = { bytes_methods[] = {
{"__alloc__", (PyCFunction)bytes_alloc, METH_NOARGS, alloc_doc}, {"__alloc__", (PyCFunction)bytes_alloc, METH_NOARGS, alloc_doc},
{"__reduce__", (PyCFunction)bytes_reduce, METH_NOARGS, reduce_doc}, {"__reduce__", (PyCFunction)bytes_reduce, METH_NOARGS, reduce_doc},
{"__sizeof__", (PyCFunction)bytes_sizeof, METH_NOARGS, sizeof_doc},
{"append", (PyCFunction)bytes_append, METH_O, append__doc__}, {"append", (PyCFunction)bytes_append, METH_O, append__doc__},
{"capitalize", (PyCFunction)stringlib_capitalize, METH_NOARGS, {"capitalize", (PyCFunction)stringlib_capitalize, METH_NOARGS,
_Py_capitalize__doc__}, _Py_capitalize__doc__},
......
...@@ -513,6 +513,29 @@ frame_clear(PyFrameObject *f) ...@@ -513,6 +513,29 @@ frame_clear(PyFrameObject *f)
} }
} }
static PyObject *
frame_sizeof(PyFrameObject *f)
{
Py_ssize_t res, extras, ncells, nfrees;
ncells = PyTuple_GET_SIZE(f->f_code->co_cellvars);
nfrees = PyTuple_GET_SIZE(f->f_code->co_freevars);
extras = f->f_code->co_stacksize + f->f_code->co_nlocals +
ncells + nfrees;
// subtract one as it is already included in PyFrameObject
res = sizeof(PyFrameObject) + (extras-1) * sizeof(PyObject *);
return PyLong_FromSsize_t(res);
}
PyDoc_STRVAR(sizeof__doc__,
"F.__sizeof__() -> size of F in memory, in bytes");
static PyMethodDef frame_methods[] = {
{"__sizeof__", (PyCFunction)frame_sizeof, METH_NOARGS,
sizeof__doc__},
{NULL, NULL} /* sentinel */
};
PyTypeObject PyFrame_Type = { PyTypeObject PyFrame_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0) PyVarObject_HEAD_INIT(&PyType_Type, 0)
...@@ -542,7 +565,7 @@ PyTypeObject PyFrame_Type = { ...@@ -542,7 +565,7 @@ PyTypeObject PyFrame_Type = {
0, /* tp_weaklistoffset */ 0, /* tp_weaklistoffset */
0, /* tp_iter */ 0, /* tp_iter */
0, /* tp_iternext */ 0, /* tp_iternext */
0, /* tp_methods */ frame_methods, /* tp_methods */
frame_memberlist, /* tp_members */ frame_memberlist, /* tp_members */
frame_getsetlist, /* tp_getset */ frame_getsetlist, /* tp_getset */
0, /* tp_base */ 0, /* tp_base */
......
...@@ -3638,9 +3638,7 @@ long_sizeof(PyLongObject *v) ...@@ -3638,9 +3638,7 @@ long_sizeof(PyLongObject *v)
{ {
Py_ssize_t res; Py_ssize_t res;
res = sizeof(PyLongObject) + abs(Py_SIZE(v)) * sizeof(digit); res = sizeof(PyVarObject) + abs(Py_SIZE(v))*sizeof(digit);
if (Py_SIZE(v) != 0)
res -= sizeof(digit);
return PyLong_FromSsize_t(res); return PyLong_FromSsize_t(res);
} }
......
...@@ -1944,6 +1944,18 @@ done: ...@@ -1944,6 +1944,18 @@ done:
PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
static PyObject *
set_sizeof(PySetObject *so)
{
Py_ssize_t res;
res = sizeof(PySetObject);
if (so->table != so->smalltable)
res = res + (so->mask + 1) * sizeof(setentry);
return PyLong_FromSsize_t(res);
}
PyDoc_STRVAR(sizeof_doc, "S.__sizeof__() -> size of S in memory, in bytes");
static int static int
set_init(PySetObject *self, PyObject *args, PyObject *kwds) set_init(PySetObject *self, PyObject *args, PyObject *kwds)
{ {
...@@ -2011,6 +2023,8 @@ static PyMethodDef set_methods[] = { ...@@ -2011,6 +2023,8 @@ static PyMethodDef set_methods[] = {
reduce_doc}, reduce_doc},
{"remove", (PyCFunction)set_remove, METH_O, {"remove", (PyCFunction)set_remove, METH_O,
remove_doc}, remove_doc},
{"__sizeof__", (PyCFunction)set_sizeof, METH_NOARGS,
sizeof_doc},
{"symmetric_difference",(PyCFunction)set_symmetric_difference, METH_O, {"symmetric_difference",(PyCFunction)set_symmetric_difference, METH_O,
symmetric_difference_doc}, symmetric_difference_doc},
{"symmetric_difference_update",(PyCFunction)set_symmetric_difference_update, METH_O, {"symmetric_difference_update",(PyCFunction)set_symmetric_difference_update, METH_O,
...@@ -2127,6 +2141,8 @@ static PyMethodDef frozenset_methods[] = { ...@@ -2127,6 +2141,8 @@ static PyMethodDef frozenset_methods[] = {
issuperset_doc}, issuperset_doc},
{"__reduce__", (PyCFunction)set_reduce, METH_NOARGS, {"__reduce__", (PyCFunction)set_reduce, METH_NOARGS,
reduce_doc}, reduce_doc},
{"__sizeof__", (PyCFunction)set_sizeof, METH_NOARGS,
sizeof_doc},
{"symmetric_difference",(PyCFunction)set_symmetric_difference, METH_O, {"symmetric_difference",(PyCFunction)set_symmetric_difference, METH_O,
symmetric_difference_doc}, symmetric_difference_doc},
{"union", (PyCFunction)set_union, METH_VARARGS, {"union", (PyCFunction)set_union, METH_VARARGS,
......
...@@ -8350,20 +8350,8 @@ PyDoc_STRVAR(p_format__doc__, ...@@ -8350,20 +8350,8 @@ PyDoc_STRVAR(p_format__doc__,
static PyObject * static PyObject *
unicode__sizeof__(PyUnicodeObject *v) unicode__sizeof__(PyUnicodeObject *v)
{ {
PyObject *res = NULL, *defsize = NULL; return PyLong_FromSsize_t(sizeof(PyUnicodeObject) +
res = PyLong_FromSsize_t(sizeof(PyUnicodeObject) +
sizeof(Py_UNICODE) * (v->length + 1)); sizeof(Py_UNICODE) * (v->length + 1));
if (v->defenc) {
defsize = PyObject_CallMethod(v->defenc, "__sizeof__", NULL);
if (defsize == NULL) {
Py_DECREF(res);
return NULL;
}
res = PyNumber_Add(res, defsize);
Py_DECREF(defsize);
}
return res;
} }
PyDoc_STRVAR(sizeof__doc__, PyDoc_STRVAR(sizeof__doc__,
......
...@@ -610,9 +610,16 @@ sys_mdebug(PyObject *self, PyObject *args) ...@@ -610,9 +610,16 @@ sys_mdebug(PyObject *self, PyObject *args)
#endif /* USE_MALLOPT */ #endif /* USE_MALLOPT */
static PyObject * static PyObject *
sys_getsizeof(PyObject *self, PyObject *args) sys_getsizeof(PyObject *self, PyObject *args, PyObject *kwds)
{ {
static PyObject * str__sizeof__ = NULL; PyObject *res = NULL;
static PyObject *str__sizeof__, *gc_head_size = NULL;
static char *kwlist[] = {"object", "default", 0};
PyObject *o, *dflt = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:getsizeof",
kwlist, &o, &dflt))
return NULL;
/* Initialize static variable needed by _PyType_Lookup */ /* Initialize static variable needed by _PyType_Lookup */
if (str__sizeof__ == NULL) { if (str__sizeof__ == NULL) {
...@@ -621,24 +628,47 @@ sys_getsizeof(PyObject *self, PyObject *args) ...@@ -621,24 +628,47 @@ sys_getsizeof(PyObject *self, PyObject *args)
return NULL; return NULL;
} }
/* Type objects */ /* Initialize static variable for GC head size */
if (PyType_Check(args)){ if (gc_head_size == NULL) {
PyObject *method = _PyType_Lookup(Py_TYPE(args), gc_head_size = PyLong_FromSsize_t(sizeof(PyGC_Head));
str__sizeof__); if (gc_head_size == NULL)
if (method == NULL) { return NULL;
}
/* Make sure the type is initialized. float gets initialized late */
if (PyType_Ready(Py_TYPE(o)) < 0)
return NULL;
PyObject *method = _PyType_Lookup(Py_TYPE(o), str__sizeof__);
if (method == NULL)
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"Type %.100s doesn't define __sizeof__", "Type %.100s doesn't define __sizeof__",
Py_TYPE(args)->tp_name); Py_TYPE(o)->tp_name);
return NULL; else
res = PyObject_CallFunctionObjArgs(method, o, NULL);
/* Has a default value been given */
if ((res == NULL) && (dflt != NULL) &&
PyErr_ExceptionMatches(PyExc_TypeError))
{
PyErr_Clear();
Py_INCREF(dflt);
return dflt;
} }
return PyObject_CallFunctionObjArgs(method, args, NULL); else if (res == NULL)
return res;
/* add gc_head size */
if (PyObject_IS_GC(o)) {
PyObject *tmp = res;
res = PyNumber_Add(tmp, gc_head_size);
Py_DECREF(tmp);
} }
else return res;
return PyObject_CallMethod(args, "__sizeof__", NULL);
} }
PyDoc_STRVAR(getsizeof_doc, PyDoc_STRVAR(getsizeof_doc,
"getsizeof(object) -> int\n\ "getsizeof(object, default) -> int\n\
\n\ \n\
Return the size of object in bytes."); Return the size of object in bytes.");
...@@ -845,7 +875,8 @@ static PyMethodDef sys_methods[] = { ...@@ -845,7 +875,8 @@ static PyMethodDef sys_methods[] = {
{"getrefcount", (PyCFunction)sys_getrefcount, METH_O, getrefcount_doc}, {"getrefcount", (PyCFunction)sys_getrefcount, METH_O, getrefcount_doc},
{"getrecursionlimit", (PyCFunction)sys_getrecursionlimit, METH_NOARGS, {"getrecursionlimit", (PyCFunction)sys_getrecursionlimit, METH_NOARGS,
getrecursionlimit_doc}, getrecursionlimit_doc},
{"getsizeof", sys_getsizeof, METH_O, getsizeof_doc}, {"getsizeof", (PyCFunction)sys_getsizeof,
METH_VARARGS | METH_KEYWORDS, getsizeof_doc},
{"_getframe", sys_getframe, METH_VARARGS, getframe_doc}, {"_getframe", sys_getframe, METH_VARARGS, getframe_doc},
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
{"getwindowsversion", (PyCFunction)sys_getwindowsversion, METH_NOARGS, {"getwindowsversion", (PyCFunction)sys_getwindowsversion, METH_NOARGS,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment