Rev 66: Add a 'scanner.get_recursive_size' function. in http://bazaar.launchpad.net/~jameinel/meliae/trunk

John Arbash Meinel john at arbash-meinel.com
Tue Sep 8 18:41:16 BST 2009


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

------------------------------------------------------------
revno: 66
revision-id: john at arbash-meinel.com-20090908174103-17nem9vf7bz8r2x7
parent: john at arbash-meinel.com-20090908171916-ekr6d1c8gb0e0eih
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: trunk
timestamp: Tue 2009-09-08 12:41:03 -0500
message:
  Add a 'scanner.get_recursive_size' function.
  This is meant to help in interactive analysis. So that we
  can try to quickly determine the size of a simple structure
  in memory.
-------------- next part --------------
=== modified file 'meliae/scanner.py'
--- a/meliae/scanner.py	2009-09-08 17:19:16 +0000
+++ b/meliae/scanner.py	2009-09-08 17:41:03 +0000
@@ -80,3 +80,35 @@
     for obj in all_objs:
         _scanner.dump_object_info(outf, obj, nodump=nodump,
                                   recurse_depth=recurse_depth)
+
+
+def get_recursive_size(obj):
+    """Get the memory referenced from this object.
+
+    This returns the memory of the direct object, and all of the memory
+    referenced by child objects. It also returns the total number of objects.
+    """
+    total_size = 0
+    pending = [obj]
+    last_item = 0
+    seen = _intset.IDSet()
+    size_of = _scanner.size_of
+    while last_item >= 0:
+        item = pending[last_item]
+        last_item -= 1
+        id_item = id(item)
+        if id_item in seen:
+            continue
+        seen.add(id_item)
+        total_size += size_of(item)
+        for child in gc.get_referents(item):
+            if id(child) not in seen:
+                last_item += 1
+                if len(pending) > last_item:
+                    pending[last_item] = child
+                else:
+                    pending.append(child)
+    return len(seen), total_size
+
+
+size_of = _scanner.size_of

=== modified file 'meliae/tests/test_scanner.py'
--- a/meliae/tests/test_scanner.py	2009-09-08 17:19:16 +0000
+++ b/meliae/tests/test_scanner.py	2009-09-08 17:41:03 +0000
@@ -76,3 +76,40 @@
         # We have a reference cycle here, but we should not loop endlessly :)
         self.assertDumpAllReferenced([a, b, c, l], l)
         self.assertDumpAllReferenced([a, b, c, l], c)
+
+
+class TestGetRecursiveSize(tests.TestCase):
+
+    def assertRecursiveSize(self, n_objects, total_size, obj):
+        self.assertEqual((n_objects, total_size),
+                         scanner.get_recursive_size(obj))
+
+    def test_single_object(self):
+        i = 1
+        self.assertRecursiveSize(1, scanner.size_of(i), i)
+        d = {}
+        self.assertRecursiveSize(1, scanner.size_of(d), d)
+        l = []
+        self.assertRecursiveSize(1, scanner.size_of(l), l)
+
+    def test_referenced(self):
+        s1 = 'this is a simple string'
+        s2 = 'and this is another one'
+        s3 = s1 + s2
+        s4 = 'this is a' + ' simple string'# same as s1, but diff object
+        self.assertTrue(s1 is not s4)
+        self.assertTrue(s1 == s4)
+        d = {s1:s2, s3:s4}
+        total_size = (scanner.size_of(s1) + scanner.size_of(s2)
+                      + scanner.size_of(s3) + scanner.size_of(s4)
+                      + scanner.size_of(d))
+        self.assertRecursiveSize(5, total_size, d)
+
+    def test_recursive(self):
+        s1 = 'this is a simple string'
+        s2 = 'and this is another one'
+        l = [s1, s2]
+        l.append(l)
+        total_size = (scanner.size_of(s1) + scanner.size_of(s2)
+                      + scanner.size_of(l))
+        self.assertRecursiveSize(3, total_size, l)



More information about the bazaar-commits mailing list