Rev 125: Start respecting the __sizeof__ attribute if available. in http://bazaar.launchpad.net/~jameinel/meliae/sizeof

John Arbash Meinel john at arbash-meinel.com
Wed Dec 30 16:25:43 GMT 2009


At http://bazaar.launchpad.net/~jameinel/meliae/sizeof

------------------------------------------------------------
revno: 125
revision-id: john at arbash-meinel.com-20091230162515-13m5fut2gf56m8fu
parent: john at arbash-meinel.com-20091229230129-tngefk0eip23ktax
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: sizeof
timestamp: Wed 2009-12-30 10:25:15 -0600
message:
  Start respecting the __sizeof__ attribute if available.
-------------- next part --------------
=== modified file 'meliae/_scanner.pyx'
--- a/meliae/_scanner.pyx	2009-10-07 21:39:53 +0000
+++ b/meliae/_scanner.pyx	2009-12-30 16:25:15 +0000
@@ -1,14 +1,14 @@
 # Copyright (C) 2009 Canonical Ltd
-# 
+#
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License version 3 as
 # published by the Free Software Foundation.
-# 
+#
 # This program is distributed in the hope that it will be useful, but
 # WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 # General Public License for more details.
-# 
+#
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 

=== modified file 'meliae/_scanner_core.c'
--- a/meliae/_scanner_core.c	2009-10-18 18:35:04 +0000
+++ b/meliae/_scanner_core.c	2009-12-30 16:25:15 +0000
@@ -1,14 +1,14 @@
 /* Copyright (C) 2009 Canonical Ltd
- * 
+ *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 3 as
  * published by the Free Software Foundation.
- * 
+ *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
@@ -99,6 +99,40 @@
             + num_entries * c_obj->ob_type->tp_itemsize;
 }
 
+Py_ssize_t
+_size_of_from__sizeof__(PyObject *c_obj)
+{
+    PyObject *size_obj = NULL;
+    Py_ssize_t size = -1;
+
+    if (PyType_CheckExact(c_obj)) {
+        // Types themselves may have a __sizeof__ attribute, but it is the
+        // unbound method, which takes an instance
+        return -1;
+    }
+    size_obj = PyObject_CallMethod(c_obj, "__sizeof__", NULL);
+    if (size_obj == NULL) {
+        // Not sure what happened, but this won't work, it could be a simple
+        // attribute error, or it could be something else.
+        PyErr_Clear();
+        return -1;
+    }
+    size = PyInt_AsSsize_t(size_obj);
+    if (size == -1) {
+        // Probably an error occurred, we don't know for sure, but we might as
+        // well just claim that we don't know the size. We *could* check
+        // PyErr_Occurred(), but if we are just clearing it anyway...
+        PyErr_Clear();
+        return -1;
+    }
+    // There is one trick left. Namely, __sizeof__ doesn't seem to include the
+    // GC overhead, so let's add that back in
+    if (PyType_HasFeature(c_obj->ob_type, Py_TPFLAGS_HAVE_GC)) {
+        size += sizeof(PyGC_Head);
+    }
+    return size;
+}
+
 
 Py_ssize_t
 _size_of_list(PyListObject *c_obj)
@@ -147,6 +181,8 @@
 Py_ssize_t
 _size_of(PyObject *c_obj)
 {
+    Py_ssize_t size;
+
     if PyList_Check(c_obj) {
         return _size_of_list((PyListObject *)c_obj);
     } else if PyAnySet_Check(c_obj) {
@@ -157,6 +193,11 @@
         return _size_of_unicode((PyUnicodeObject *)c_obj);
     }
 
+    size = _size_of_from__sizeof__(c_obj);
+    if (size != -1) {
+        return size;
+    }
+
     if (c_obj->ob_type->tp_itemsize != 0) {
         // Variable length object with inline storage
         // total size is tp_itemsize * ob_size

=== modified file 'meliae/_scanner_core.h'
--- a/meliae/_scanner_core.h	2009-10-07 21:39:53 +0000
+++ b/meliae/_scanner_core.h	2009-12-30 16:25:15 +0000
@@ -1,15 +1,15 @@
 /* Copyright (C) 2009 Canonical Ltd
- * 
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

=== modified file 'meliae/loader.py'
--- a/meliae/loader.py	2009-12-23 16:55:05 +0000
+++ b/meliae/loader.py	2009-12-30 16:25:15 +0000
@@ -1,14 +1,14 @@
 # Copyright (C) 2009 Canonical Ltd
-# 
+#
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License version 3 as
 # published by the Free Software Foundation.
-# 
+#
 # This program is distributed in the hope that it will be useful, but
 # WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 # General Public License for more details.
-# 
+#
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 

=== modified file 'meliae/tests/test__scanner.py'
--- a/meliae/tests/test__scanner.py	2009-10-18 18:35:04 +0000
+++ b/meliae/tests/test__scanner.py	2009-12-30 16:25:15 +0000
@@ -154,6 +154,19 @@
     def test_None(self):
         self.assertSizeOf(2, None, has_gc=False)
 
+    def test__sizeof__instance(self):
+        # __sizeof__ appears to have been introduced in python 2.6, and
+        # is meant to return the number of bytes allocated to this
+        # object. It does not include GC overhead, that seems to be added back
+        # in as part of sys.getsizeof(). So meliae does the same in size_of()
+        class CustomSize(object):
+            def __init__(self, size):
+                self.size = size
+            def __sizeof__(self):
+                return self.size
+        self.assertSizeOf(0, CustomSize(10), 10, has_gc=True)
+        self.assertSizeOf(0, CustomSize(20), 20, has_gc=True)
+
 
 def _string_to_json(s):
     out = ['"']



More information about the bazaar-commits mailing list