zoukankan      html  css  js  c++  java
  • __sizeof__()

    https://bugs.python.org/issue2898

    https://bugs.python.org/file10353/footprint.patch

    Index: Python/sysmodule.c
    ===================================================================
    --- Python/sysmodule.c	(.../trunk)	(revision 63363)
    +++ Python/sysmodule.c	(.../branches/okkoto-sizeof)	(working copy)
    @@ -640,6 +640,46 @@
     #endif /* USE_MALLOPT */
     
     static PyObject *
    +sys_getsizeof(PyObject *self, PyObject *args)
    +{
    +	static PyObject * str__sizeof__ = NULL;
    +
    +	/* Initialize static variable needed by _PyType_Lookup */
    +	if (str__sizeof__ == NULL) {
    +		str__sizeof__ = PyString_InternFromString("__sizeof__");
    +		if (str__sizeof__ == NULL)
    +			return NULL;
    +	}
    +
    +	/* Type objects */
    +	if (PyType_Check(args)){
    +		PyObject *method = _PyType_Lookup(Py_TYPE(args),
    +						  str__sizeof__);
    +		if (method == NULL) {
    +			PyErr_Format(PyExc_TypeError,
    +				     "Type %.100s doesn't define __sizeof__",
    +				     Py_TYPE(args)->tp_name);
    +			return NULL;
    +		}
    +		/* And call it, binding it to the value */
    +		return PyObject_CallFunctionObjArgs(method, args, NULL);
    +	} 
    +	/* Instance of old-style classes */
    +	else if(PyInstance_Check(args))
    +		return PyInt_FromSsize_t(PyInstance_Type.tp_basicsize);
    +	/* Old-style class */
    +	else if (PyClass_Check(args))
    +		return PyInt_FromSsize_t(PyClass_Type.tp_basicsize);
    +	else
    +		return PyObject_CallMethod(args, "__sizeof__", NULL);
    +}
    +
    +PyDoc_STRVAR(getsizeof_doc,
    +"getsizeof(object) -> int
    
    +
    
    +Return the size of object in bytes.");
    +
    +static PyObject *
     sys_getrefcount(PyObject *self, PyObject *arg)
     {
     	return PyInt_FromSsize_t(arg->ob_refcnt);
    @@ -850,6 +890,7 @@
     	{"getrefcount",	(PyCFunction)sys_getrefcount, METH_O, getrefcount_doc},
     	{"getrecursionlimit", (PyCFunction)sys_getrecursionlimit, METH_NOARGS,
     	 getrecursionlimit_doc},
    + 	{"getsizeof",	sys_getsizeof,  METH_O, getsizeof_doc},
     	{"_getframe", sys_getframe, METH_VARARGS, getframe_doc},
     #ifdef MS_WINDOWS
     	{"getwindowsversion", (PyCFunction)sys_getwindowsversion, METH_NOARGS,
    @@ -1030,6 +1071,7 @@
     getprofile() -- get the global profiling function
    
     getrefcount() -- return the reference count for an object (plus one :-)
    
     getrecursionlimit() -- return the max recursion depth for the interpreter
    
    +getsizeof() -- return the size of an object in bytes
    
     gettrace() -- get the global debug tracing function
    
     setcheckinterval() -- control how often the interpreter checks for events
    
     setdlopenflags() -- set the flags to be used for dlopen() calls
    
    Index: Objects/typeobject.c
    ===================================================================
    --- Objects/typeobject.c	(.../trunk)	(revision 63363)
    +++ Objects/typeobject.c	(.../branches/okkoto-sizeof)	(working copy)
    @@ -3398,6 +3398,20 @@
             return result;
     }
     
    +static PyObject *
    +object_sizeof(PyObject *self, PyObject *args)
    +{
    +	Py_ssize_t res, isize;
    +
    +	res = 0;
    +	isize = self->ob_type->tp_itemsize;
    +	if (isize > 0)
    +		res = self->ob_type->ob_size * isize;
    +	res += self->ob_type->tp_basicsize;
    +
    +	return PyInt_FromSsize_t(res);	 
    +}
    +
     static PyMethodDef object_methods[] = {
     	{"__reduce_ex__", object_reduce_ex, METH_VARARGS,
     	 PyDoc_STR("helper for pickle")},
    @@ -3407,6 +3421,8 @@
     	 object_subclasshook_doc},
             {"__format__", object_format, METH_VARARGS,
              PyDoc_STR("default object formatter")},
    +        {"__sizeof__", object_sizeof, METH_NOARGS,
    +         PyDoc_STR("__sizeof__() -> size of object in bytes")},
     	{0}
     };
     
    Index: Objects/dictobject.c
    ===================================================================
    --- Objects/dictobject.c	(.../trunk)	(revision 63363)
    +++ Objects/dictobject.c	(.../branches/okkoto-sizeof)	(working copy)
    @@ -2032,7 +2032,17 @@
     	return dictiter_new(dict, &PyDictIterItem_Type);
     }
     
    +static PyObject *
    +dict_sizeof(PyDictObject *mp)
    +{
    +	Py_ssize_t res;
     
    +	res = sizeof(PyDictObject) + sizeof(mp->ma_table);
    +	if (mp->ma_table != mp->ma_smalltable)
    +		res = res + (mp->ma_mask + 1) * sizeof(PyDictEntry);
    +	return PyInt_FromSsize_t(res);
    +}
    +
     PyDoc_STRVAR(has_key__doc__,
     "D.has_key(k) -> True if D has a key k, else False");
     
    @@ -2041,6 +2051,9 @@
     
     PyDoc_STRVAR(getitem__doc__, "x.__getitem__(y) <==> x[y]");
     
    +PyDoc_STRVAR(sizeof__doc__,
    +"D.__sizeof__() -> size of D in bytes");
    +
     PyDoc_STRVAR(get__doc__,
     "D.get(k[,d]) -> D[k] if k in D, else d.  d defaults to None.");
     
    @@ -2092,6 +2105,8 @@
     	 contains__doc__},
     	{"__getitem__", (PyCFunction)dict_subscript,	METH_O | METH_COEXIST,
     	 getitem__doc__},
    +	{"__sizeof__",	(PyCFunction)dict_sizeof,	METH_NOARGS,
    +	 sizeof__doc__},
     	{"has_key",	(PyCFunction)dict_has_key,      METH_O,
     	 has_key__doc__},
     	{"get",         (PyCFunction)dict_get,          METH_VARARGS,
    Index: Objects/listobject.c
    ===================================================================
    --- Objects/listobject.c	(.../trunk)	(revision 63363)
    +++ Objects/listobject.c	(.../branches/okkoto-sizeof)	(working copy)
    @@ -2420,6 +2420,15 @@
     	return 0;
     }
     
    +static PyObject *
    +list_sizeof(PyListObject *self)
    +{
    +	Py_ssize_t res;
    +
    +	res = sizeof(PyListObject) + self->allocated * sizeof(void*);
    +	return PyInt_FromSsize_t(res);
    +}
    +
     static PyObject *list_iter(PyObject *seq);
     static PyObject *list_reversed(PyListObject* seq, PyObject* unused);
     
    @@ -2427,6 +2436,8 @@
     "x.__getitem__(y) <==> x[y]");
     PyDoc_STRVAR(reversed_doc,
     "L.__reversed__() -- return a reverse iterator over the list");
    +PyDoc_STRVAR(sizeof_doc,
    +"L.__sizeof__() -- size of L in bytes");
     PyDoc_STRVAR(append_doc,
     "L.append(object) -- append object to end");
     PyDoc_STRVAR(extend_doc,
    @@ -2452,6 +2463,7 @@
     static PyMethodDef list_methods[] = {
     	{"__getitem__", (PyCFunction)list_subscript, METH_O|METH_COEXIST, getitem_doc},
     	{"__reversed__",(PyCFunction)list_reversed, METH_NOARGS, reversed_doc},
    +	{"__sizeof__",  (PyCFunction)list_sizeof, METH_NOARGS, sizeof_doc},
     	{"append",	(PyCFunction)listappend,  METH_O, append_doc},
     	{"insert",	(PyCFunction)listinsert,  METH_VARARGS, insert_doc},
     	{"extend",      (PyCFunction)listextend,  METH_O, extend_doc},
    Index: Objects/longobject.c
    ===================================================================
    --- Objects/longobject.c	(.../trunk)	(revision 63363)
    +++ Objects/longobject.c	(.../branches/okkoto-sizeof)	(working copy)
    @@ -3441,6 +3441,17 @@
     	return NULL;
     }
     
    +static PyObject *
    +long_sizeof(PyLongObject *v)
    +{
    +	Py_ssize_t res;
    +
    +	res = sizeof(PyLongObject) + abs(v->ob_size) * sizeof(digit);
    +        if (v->ob_size != 0)
    +		res -=  sizeof(digit);
    +	return PyInt_FromSsize_t(res);
    +}
    +
     #if 0
     static PyObject *
     long_is_finite(PyObject *v)
    @@ -3460,6 +3471,8 @@
              "Truncating an Integral returns itself."},
     	{"__getnewargs__",	(PyCFunction)long_getnewargs,	METH_NOARGS},
             {"__format__", (PyCFunction)long__format__, METH_VARARGS},
    +	{"__sizeof__",	(PyCFunction)long_sizeof, METH_NOARGS,
    +	 "Returns size in bytes"},
     	{NULL,		NULL}		/* sentinel */
     };
     
    Index: Objects/stringobject.c
    ===================================================================
    --- Objects/stringobject.c	(.../trunk)	(revision 63363)
    +++ Objects/stringobject.c	(.../branches/okkoto-sizeof)	(working copy)
    @@ -3920,6 +3920,17 @@
         return NULL;
     }
     
    +PyDoc_STRVAR(sizeof__doc__,
    +"S.__sizeof__() -> size of S in bytes");
    +
    +static PyObject *
    +string_sizeof(PyStringObject *v)
    +{
    +	Py_ssize_t res;
    +	res = sizeof(PyStringObject) + v->ob_size * v->ob_type->tp_itemsize;
    +	return PyInt_FromSsize_t(res);
    +}
    +
     #undef SPLIT_APPEND
     #undef SPLIT_ADD
     #undef MAX_PREALLOC
    @@ -3998,6 +4009,8 @@
     	 expandtabs__doc__},
     	{"splitlines", (PyCFunction)string_splitlines, METH_VARARGS,
     	 splitlines__doc__},
    +	{"__sizeof__", (PyCFunction)string_sizeof, METH_NOARGS,
    +	 sizeof__doc__},
     	{"__getnewargs__",	(PyCFunction)string_getnewargs,	METH_NOARGS},
     	{NULL,     NULL}		     /* sentinel */
     };
    Index: Doc/library/sys.rst
    ===================================================================
    --- Doc/library/sys.rst	(.../trunk)	(revision 63363)
    +++ Doc/library/sys.rst	(.../branches/okkoto-sizeof)	(working copy)
    @@ -409,6 +409,16 @@
        :func:`setrecursionlimit`.
     
     
    +.. function:: getsizeof(object)
    +
    +   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
    +   does not have to hold true for third-party extensions as it is implementation 
    +   specific.
    +
    +   .. versionadded:: 2.6
    +
    +
     .. function:: _getframe([depth])
     
        Return a frame object from the call stack.  If optional integer *depth* is
    Index: Lib/test/test_sys.py
    ===================================================================
    --- Lib/test/test_sys.py	(.../trunk)	(revision 63363)
    +++ Lib/test/test_sys.py	(.../branches/okkoto-sizeof)	(working copy)
    @@ -1,6 +1,6 @@
     # -*- coding: iso-8859-1 -*-
     import unittest, test.test_support
    -import sys, cStringIO
    +import sys, cStringIO, os
     
     class SysModuleTest(unittest.TestCase):
     
    @@ -385,8 +385,156 @@
     ##        self.assert_(r[0][2] > 100, r[0][2])
     ##        self.assert_(r[1][2] > 100, r[1][2])
     
    +
    +class SizeofTest(unittest.TestCase):
    +
    +    def setUp(self):
    +        import struct
    +        self.i = len(struct.pack('i', 0))
    +        self.l = len(struct.pack('l', 0))
    +        self.p = len(struct.pack('P', 0))
    +        self.headersize = self.l + self.p
    +        if hasattr(sys, "gettotalrefcount"):
    +            self.headersize += 2 * self.p
    +        self.file = open(test.test_support.TESTFN, 'wb')
    +
    +    def tearDown(self):
    +        self.file.close()
    +        os.remove(test.test_support.TESTFN)
    +
    +    def check_sizeof(self, o, size):
    +        result = sys.getsizeof(o)
    +        msg = 'wrong size for %s: got %d, expected %d' 
    +            % (type(o), result, size)
    +        self.assertEqual(result, size, msg)
    +
    +    def align(self, value):
    +        mod = value % self.p
    +        if mod != 0:
    +            return value - mod + self.p
    +        else:
    +            return value
    +
    +    def test_align(self):
    +        self.assertTrue( (self.align(0) % self.p) == 0 )
    +        self.assertTrue( (self.align(1) % self.p) == 0 )
    +        self.assertTrue( (self.align(3) % self.p) == 0 )
    +        self.assertTrue( (self.align(4) % self.p) == 0 )
    +        self.assertTrue( (self.align(7) % self.p) == 0 )
    +        self.assertTrue( (self.align(8) % self.p) == 0 )
    +        self.assertTrue( (self.align(9) % self.p) == 0 )
    +
    +    def test_standardtypes(self):
    +        i = self.i
    +        l = self.l
    +        p = self.p
    +        h = self.headersize
    +        # bool
    +        self.check_sizeof(True, h + l)
    +        # buffer
    +        self.check_sizeof(buffer(''), h + 2*p + 2*l + self.align(i) +l)
    +        # bytearray
    +        self.check_sizeof(bytes(), h + self.align(i) + l + p)
    +        # cell
    +        def get_cell():
    +            x = 42
    +            def inner():
    +                return x
    +            return inner
    +        self.check_sizeof(get_cell().func_closure[0], h + p)
    +        # old-style class
    +        class class_oldstyle():
    +            def method():
    +                pass
    +        self.check_sizeof(class_oldstyle, h + 6*p)
    +        # instance
    +        self.check_sizeof(class_oldstyle(), h + 3*p)
    +        # method
    +        self.check_sizeof(class_oldstyle().method, h + 4*p)
    +        # code
    +        self.check_sizeof(get_cell().func_code, h + self.align(4*i) + 8*p +
    +                            self.align(i) + 2*p)
    +        # complex
    +        self.check_sizeof(complex(0,1), h + 2*8)
    +        # enumerate
    +        self.check_sizeof(enumerate([]), h + l + 3*p)
    +        # reverse
    +        self.check_sizeof(reversed(''), h + l + p )
    +        # file
    +        self.check_sizeof(self.file, h + 4*p + self.align(2*i) + 4*p +
    +                            self.align(3*i) + 2*p + self.align(i))
    +        # float
    +        self.check_sizeof(float(0), h + 8)
    +        # function
    +        def func(): pass
    +        self.check_sizeof(func, h + 9 * l)
    +        class c():
    +            @staticmethod
    +            def foo():
    +                pass
    +            @classmethod
    +            def bar(cls):
    +                pass
    +            # staticmethod
    +            self.check_sizeof(foo, h + l)
    +            # classmethod
    +            self.check_sizeof(bar, h + l)
    +        # generator
    +        def get_gen(): yield 1
    +        self.check_sizeof(get_gen(), h + p + self.align(i) + 2*p)
    +        # integer
    +        self.check_sizeof(1, h + l)
    +        # builtin_function_or_method
    +        self.check_sizeof(abs, h + 3*p)
    +        # module
    +        self.check_sizeof(unittest, h + p)
    +        # xange
    +        self.check_sizeof(xrange(1), h + 3*p)
    +        # slice
    +        self.check_sizeof(slice(0), h + 3*p)
    +
    +        h += l
    +        # new-style class
    +        class class_newstyle(object):
    +            def method():
    +                pass
    +        # type (PyTypeObject + PyNumberMethods +  PyMappingMethods +
    +        #       PySequenceMethods +  PyBufferProcs)
    +        len_typeobject = p + 2*l + 15*p + l + 4*p + l + 9*p + l + 11*p
    +        self.check_sizeof(class_newstyle, h + 
    +                              len_typeobject + 42*p + 10*p + 3*p + 6*p)
    +
    +
    +    def test_specialtypes(self):
    +        i = self.i
    +        l = self.l
    +        p = self.p
    +        h = self.headersize
    +        # dict
    +        self.check_sizeof({}, h + 3*l + 3*p + 8*(l + 2*p))
    +        longdict = {1:1, 2:2, 3:3, 4:4, 5:5, 6:6, 7:7, 8:8}
    +        self.check_sizeof(longdict, h + 3*l + 3*p + 8*(l + 2*p) + 16*(l + 2*p))
    +        # list
    +        self.check_sizeof([], h + l + p + l)
    +        self.check_sizeof([1, 2, 3], h + l + p + l + 3*l)
    +
    +        h += l
    +        # long
    +        self.check_sizeof(0L, h + self.align(2))
    +        self.check_sizeof(1L, h + self.align(2))
    +        self.check_sizeof(-1L, h + self.align(2))
    +        self.check_sizeof(32768L, h + self.align(2) + 2)
    +        self.check_sizeof(32768L*32768L-1, h + self.align(2) + 2)
    +        self.check_sizeof(32768L*32768L, h + self.align(2) + 4)
    +        # string
    +        self.check_sizeof('', h + l + self.align(i + 1))
    +        self.check_sizeof('abc', h + l + self.align(i + 1) + 3)
    +
    +
     def test_main():
    -    test.test_support.run_unittest(SysModuleTest)
    +    test_classes = (SysModuleTest, SizeofTest)
     
    +    test.test_support.run_unittest(*test_classes)
    +
     if __name__ == "__main__":
         test_main()
    

      

    A new function, getsizeof(), takes a Python object and returns the amount of memory used by the object, measured in bytes. Built-in objects return correct results; third-party extensions may not, but can define a __sizeof__() method to return the object’s size. (Contributed by Robert Schuppenies; bpo-2898.)

  • 相关阅读:
    SQL Server, Timeout expired.all pooled connections were in use and max pool size was reached
    javascript 事件调用顺序
    Best Practices for Speeding Up Your Web Site
    C语言程序设计 使用VC6绿色版
    破解SQL Prompt 3.9的几步操作
    Master page Path (MasterPage 路径)
    几个小型数据库的比较
    CSS+DIV 完美实现垂直居中的方法
    由Response.Redirect引发的"Thread was being aborted. "异常的处理方法
    Adsutil.vbs 在脚本攻击中的妙用
  • 原文地址:https://www.cnblogs.com/rsapaper/p/7894798.html
Copyright © 2011-2022 走看看