[or-cvs] r19806: {torctl} Change the refcount debugging stuff to work recursively to a (torctl/trunk/python/TorCtl)

mikeperry at seul.org mikeperry at seul.org
Wed Jun 24 04:20:13 UTC 2009


Author: mikeperry
Date: 2009-06-24 00:20:12 -0400 (Wed, 24 Jun 2009)
New Revision: 19806

Modified:
   torctl/trunk/python/TorCtl/TorUtil.py
Log:

Change the refcount debugging stuff to work recursively to
arbitrary depth, though more than 2 is pretty damn slow.



Modified: torctl/trunk/python/TorCtl/TorUtil.py
===================================================================
--- torctl/trunk/python/TorCtl/TorUtil.py	2009-06-24 03:28:45 UTC (rev 19805)
+++ torctl/trunk/python/TorCtl/TorUtil.py	2009-06-24 04:20:12 UTC (rev 19806)
@@ -32,52 +32,78 @@
 meta_port = 9052
 meta_host = '127.0.0.1'
 
-def dump_class_ref_counts(track_referers=True, cutoff=100, rcutoff=1,
+class Referrer:
+  def __init__(self, cl):
+    self.referrers = {}
+    self.cl_name = cl
+    self.count = 0
+
+  def recurse_store(self, gc, obj, depth, max_depth):
+    if depth >= max_depth: return
+    for r in gc.get_referrers(obj):
+      if hasattr(r, "__class__"):
+        cl = r.__class__.__name__
+        # Skip frames and list iterators.. prob just us
+        if cl in ("frame", "listiterator"): continue 
+        if cl not in self.referrers:
+          self.referrers[cl] = Referrer(cl)
+        self.referrers[cl].count += 1
+        self.referrers[cl].recurse_store(gc, r, depth+1, max_depth)
+
+  def recurse_print(self, rcutoff, depth=""):
+    refs = self.referrers.keys()
+    refs.sort(lambda x, y: self.referrers[y].count - self.referrers[x].count)
+    for r in refs:
+      if self.referrers[r].count > rcutoff:
+        plog("NOTICE", "GC:  "+depth+"Refed by "+r+": "+str(self.referrers[r].count))
+        self.referrers[r].recurse_print(rcutoff, depth+" ")
+
+def dump_class_ref_counts(referrer_depth=2, cutoff=500, rcutoff=1,
         ignore=('tuple', 'list', 'function', 'dict',
-                 'builtin_function_or_method')):
+                 'builtin_function_or_method',
+                 'wrapper_descriptor')):
   """ Debugging function to track down types of objects
       that cannot be garbage collected because we hold refs to them 
       somewhere."""
   import gc
-  __dump_class_ref_counts(gc, track_referers, cutoff, rcutoff, ignore)
+  __dump_class_ref_counts(gc, referrer_depth, cutoff, rcutoff, ignore)
   gc.collect()
   plog("NOTICE", "GC: Done.")
 
-def __dump_class_ref_counts(gc, referers, cutoff, rcutoff, ignore):
+def __dump_class_ref_counts(gc, referrer_depth, cutoff, rcutoff, ignore):
   """ loil
   """
   plog("NOTICE", "GC: Gathering garbage collection stats...")
   uncollectable = gc.collect()
   class_counts = {}
-  ref_counts = {}
+  referrers = {}
   plog("NOTICE", "GC: Uncollectable objects: "+str(uncollectable))
-  for obj in gc.get_objects():
+  objs = gc.get_objects()
+  for obj in objs:
     if hasattr(obj, "__class__"):
       cl = obj.__class__.__name__
       if cl in ignore: continue
       if cl not in class_counts:
         class_counts[cl] = 0
+        referrers[cl] = Referrer(cl)
       class_counts[cl] += 1
-      if referers:
-        for r in gc.get_referrers(obj):
-          if hasattr(r, "__class__"):
-            if cl not in ref_counts:
-              ref_counts[cl] = {}
-            if r.__class__.__name__ not in ref_counts[cl]:
-              ref_counts[cl][r.__class__.__name__] = 0
-            ref_counts[cl][r.__class__.__name__] += 1
+  if referrer_depth:
+    for obj in objs:
+      if hasattr(obj, "__class__"):
+        cl = obj.__class__.__name__
+        if cl in ignore: continue
+        if class_counts[cl] > cutoff:
+          referrers[cl].recurse_store(gc, obj, 0, referrer_depth)
   classes = class_counts.keys()
   classes.sort(lambda x, y: class_counts[y] - class_counts[x])
   for c in classes:
     if class_counts[c] < cutoff: continue
     plog("NOTICE", "GC: Class "+c+": "+str(class_counts[c]))
-    if referers:
-      refs = ref_counts[c].keys()
-      refs.sort(lambda x, y: ref_counts[c][y] - ref_counts[c][x])
-      for r in refs:
-        if ref_counts[c][r] < rcutoff: continue
-        plog("NOTICE", "GC:   Refed by "+r+": "+str(ref_counts[c][r]))
+    if referrer_depth:
+      referrers[c].recurse_print(rcutoff)
 
+
+
 def read_config(filename):
   config = ConfigParser.SafeConfigParser()
   config.read(filename)



More information about the tor-commits mailing list