Explorar o código

optimized referrer search

Josh Wilson %!s(int64=15) %!d(string=hai) anos
pai
achega
9890d111c7
Modificáronse 1 ficheiros con 132 adicións e 83 borrados
  1. 132 83
      direct/src/showbase/ReferrerSearch.py

+ 132 - 83
direct/src/showbase/ReferrerSearch.py

@@ -5,10 +5,12 @@ from direct.showbase.PythonUtil import _getSafeReprNotify
 from direct.showbase.Job import Job
 from direct.showbase.Job import Job
 
 
 class ReferrerSearch(Job):
 class ReferrerSearch(Job):
-    def __init__(self, obj):
+    def __init__(self, obj, maxRefs = 100):
         Job.__init__(self, 'ReferrerSearch')
         Job.__init__(self, 'ReferrerSearch')
         self.obj = obj
         self.obj = obj
+        self.maxRefs = maxRefs
         self.found = set()
         self.found = set()
+        self.depth = 0
     
     
     def __call__(self):
     def __call__(self):
         safeReprNotify = _getSafeReprNotify()
         safeReprNotify = _getSafeReprNotify()
@@ -27,28 +29,29 @@ class ReferrerSearch(Job):
 
 
     def run(self):
     def run(self):
         safeReprNotify = _getSafeReprNotify()
         safeReprNotify = _getSafeReprNotify()
-        info = safeReprNotify.getInfo()
+        self.info = safeReprNotify.getInfo()
         safeReprNotify.setInfo(0)
         safeReprNotify.setInfo(0)
 
 
-        print 'RefPath: Beginning ReferrerSearch for', fastRepr(self.obj)
+        print 'RefPath(%s): Beginning ReferrerSearch for %s' %(self._id, fastRepr(self.obj))
 
 
         self.found = set()
         self.found = set()
         for x in self.stepGenerator(0, [self.obj]):
         for x in self.stepGenerator(0, [self.obj]):
             yield None
             yield None
             pass
             pass
         
         
-        self.obj = None
-        pass
-        
-        safeReprNotify.setInfo(info)
-
         yield Job.Done
         yield Job.Done
         pass
         pass
 
 
     def finished(self):
     def finished(self):
-        print 'RefPath: Completed ReferrerSearch for', fastRepr(self.obj)
+        print 'RefPath(%s): Finished ReferrerSearch for %s' %(self._id, fastRepr(self.obj))
         self.obj = None
         self.obj = None
-        
+
+        safeReprNotify = _getSafeReprNotify()
+        safeReprNotify.setInfo(self.info)
+        pass
+
+    def __del__(self):
+        print 'ReferrerSearch garbage collected'
         
         
     def truncateAtNewLine(self, s):
     def truncateAtNewLine(self, s):
         if s.find('\n') == -1:
         if s.find('\n') == -1:
@@ -85,142 +88,188 @@ class ReferrerSearch(Job):
     def step(self, depth, path):
     def step(self, depth, path):
         at = path[-1]
         at = path[-1]
 
 
-        if inspect.isframe(at) or \
-           (isinstance(at, dict) and \
-            at.keys() == locals().keys()) or \
-           at is self.__dict__ or \
-           id(at) in self.found:
+        if id(at) in self.found:
                # don't continue down this path
                # don't continue down this path
-               return 
+               return
 
 
-        # Now we define our 'roots'
+        # check for success
+        if (self.isAtRoot(at, path)):
+            return
 
 
+        # mark our progress after checking goal
+        self.found.add(id(at))
+
+        referrers = [ref for ref in gc.get_referrers(at) \
+                     if not (ref is path or \
+                       inspect.isframe(ref) or \
+                       (isinstance(ref, dict) and \
+                        ref.keys() == locals().keys()) or \
+                       ref is self.__dict__ or \
+                       id(ref) in self.found) ]
+
+        if (self.isManyRef(at, path, referrers)):
+            return
+            
+        while(referrers):
+            ref = referrers.pop()
+            self.depth+=1
+            for x in self.stepGenerator(depth + 1, path + [ref]):
+                pass
+            self.depth-=1
+            pass
+        pass
+
+    def stepGenerator(self, depth, path):
+        at = path[-1]
+
+        if id(at) in self.found:
+               # don't continue down this path
+               raise StopIteration 
+
+        # check for success
+        if (self.isAtRoot(at, path)):
+            raise StopIteration 
+
+        # mark our progress after checking goal
+        self.found.add(id(at))
+        
+        referrers = [ref for ref in gc.get_referrers(at) \
+                     if not (ref is path or \
+                       inspect.isframe(ref) or \
+                       (isinstance(ref, dict) and \
+                        ref.keys() == locals().keys()) or \
+                       ref is self.__dict__ or \
+                       id(ref) in self.found) ]
+
+        if (self.isManyRef(at, path, referrers)):
+            raise StopIteration 
+            
+        while(referrers):
+            ref = referrers.pop()
+            self.depth+=1
+            for x in self.stepGenerator(depth + 1, path + [ref]):
+                yield None
+                pass
+            self.depth-=1
+            pass
+
+        yield None
+        pass
+
+    def isAtRoot(self, at, path):
+        # Now we define our 'roots'
+        
         # __builtins__
         # __builtins__
         if at is __builtins__:
         if at is __builtins__:
-            sys.stdout.write("RefPath: __builtins__-> ")
+            sys.stdout.write("RefPath(%s): __builtins__-> " % self._id)
             path = list(reversed(path))
             path = list(reversed(path))
             path.insert(0,0)
             path.insert(0,0)
             for x in xrange(len(path)-1):
             for x in xrange(len(path)-1):
                 sys.stdout.write(self.myrepr(path[x], path[x+1]))
                 sys.stdout.write(self.myrepr(path[x], path[x+1]))
                 pass
                 pass
             print
             print
-            return
-
+            return True
+        
         # any module scope
         # any module scope
         if inspect.ismodule(at):
         if inspect.ismodule(at):
-            sys.stdout.write("RefPath: Module(%s)-> " % (at.__name__))
+            sys.stdout.write("RefPath(%s): Module(%s)-> " % (self._id, at.__name__))
             path = list(reversed(path))
             path = list(reversed(path))
             for x in xrange(len(path)-1):
             for x in xrange(len(path)-1):
                 sys.stdout.write(self.myrepr(path[x], path[x+1]))
                 sys.stdout.write(self.myrepr(path[x], path[x+1]))
                 pass
                 pass
             print
             print
-            return
+            return True
 
 
-        # simbase
-        if at is simbase:
-            sys.stdout.write("RefPath: simbase-> ")
+        # any class scope
+        if inspect.isclass(at):
+            sys.stdout.write("RefPath(%s): Class(%s)-> " % (self._id, at.__name__))
             path = list(reversed(path))
             path = list(reversed(path))
-            path.insert(0,0)
             for x in xrange(len(path)-1):
             for x in xrange(len(path)-1):
                 sys.stdout.write(self.myrepr(path[x], path[x+1]))
                 sys.stdout.write(self.myrepr(path[x], path[x+1]))
                 pass
                 pass
             print
             print
-            return
+            return True
 
 
-        # simbase.air
-        if at is simbase.air:
-            sys.stdout.write("RefPath: simbase.air-> ")
+        # simbase
+        if at is simbase:
+            sys.stdout.write("RefPath(%s): simbase-> " % self._id)
             path = list(reversed(path))
             path = list(reversed(path))
             path.insert(0,0)
             path.insert(0,0)
             for x in xrange(len(path)-1):
             for x in xrange(len(path)-1):
                 sys.stdout.write(self.myrepr(path[x], path[x+1]))
                 sys.stdout.write(self.myrepr(path[x], path[x+1]))
                 pass
                 pass
             print
             print
-            return
-        
-        self.found.add(id(at))
-        
-        referrers = gc.get_referrers(at)
-        while(referrers):
-            ref = referrers.pop()
-            if (ref != path):
-                self.step(depth + 1, path + [ref])
-            pass
-        pass
-    pass
-
-    def stepGenerator(self, depth, path):
-        at = path[-1]
-
-        if inspect.isframe(at) or \
-           (isinstance(at, dict) and \
-            at.keys() == locals().keys()) or \
-           at is self.__dict__ or \
-           id(at) in self.found:
-               # don't continue down this path
-               raise StopIteration 
-
-        # Now we define our 'roots'
+            return True
 
 
-        # __builtins__
-        if at is __builtins__:
-            sys.stdout.write("RefPath: __builtins__-> ")
+        # simbase.air
+        if at is simbase.air:
+            sys.stdout.write("RefPath(%s): simbase.air-> " % self._id)
             path = list(reversed(path))
             path = list(reversed(path))
             path.insert(0,0)
             path.insert(0,0)
             for x in xrange(len(path)-1):
             for x in xrange(len(path)-1):
                 sys.stdout.write(self.myrepr(path[x], path[x+1]))
                 sys.stdout.write(self.myrepr(path[x], path[x+1]))
                 pass
                 pass
             print
             print
-            raise StopIteration 
-
-        # any module scope
-        if inspect.ismodule(at):
-            sys.stdout.write("RefPath: Module(%s)-> " % (at.__name__))
+            return True
+        
+        # messenger
+        if at is messenger:
+            sys.stdout.write("RefPath(%s): messenger-> " % self._id)
             path = list(reversed(path))
             path = list(reversed(path))
+            path.insert(0,0)
             for x in xrange(len(path)-1):
             for x in xrange(len(path)-1):
                 sys.stdout.write(self.myrepr(path[x], path[x+1]))
                 sys.stdout.write(self.myrepr(path[x], path[x+1]))
                 pass
                 pass
             print
             print
-            raise StopIteration
+            return True
 
 
-        # simbase
-        if at is simbase:
-            sys.stdout.write("RefPath: simbase-> ")
+        # taskMgr
+        if at is taskMgr:
+            sys.stdout.write("RefPath(%s): taskMgr-> " % self._id)
             path = list(reversed(path))
             path = list(reversed(path))
             path.insert(0,0)
             path.insert(0,0)
             for x in xrange(len(path)-1):
             for x in xrange(len(path)-1):
                 sys.stdout.write(self.myrepr(path[x], path[x+1]))
                 sys.stdout.write(self.myrepr(path[x], path[x+1]))
                 pass
                 pass
             print
             print
-            raise StopIteration
+            return True
 
 
-        # simbase.air
-        if at is simbase.air:
-            sys.stdout.write("RefPath: simbase.air-> ")
+        # world
+        if hasattr(simbase.air, 'mainWorld') and at is simbase.air.mainWorld:
+            sys.stdout.write("RefPath(%s): mainWorld-> " % self._id)
             path = list(reversed(path))
             path = list(reversed(path))
             path.insert(0,0)
             path.insert(0,0)
             for x in xrange(len(path)-1):
             for x in xrange(len(path)-1):
                 sys.stdout.write(self.myrepr(path[x], path[x+1]))
                 sys.stdout.write(self.myrepr(path[x], path[x+1]))
                 pass
                 pass
             print
             print
-            raise StopIteration        
+            return True
+        pass
 
 
-        self.found.add(id(at))
-        
-        referrers = gc.get_referrers(at)
-        while(referrers):
-            ref = referrers.pop()
-            if (ref != path):
-                for x in self.stepGenerator(depth + 1, path + [ref]):
-                    yield None
+        return False
+
+    def isManyRef(self, at, path, referrers):
+        if (len(referrers) > self.maxRefs and \
+            at is not self.obj):
+            if not isinstance(at, (list, tuple, dict, set)):
+                sys.stdout.write("RefPath(%s): ManyRefs(%s)[%s]-> " % (self._id, len(referrers), fastRepr(at)))
+                path = list(reversed(path))
+                path.insert(0,0)
+                for x in xrange(len(path)-1):
+                    sys.stdout.write(self.myrepr(path[x], path[x+1]))
+                    pass
+                print
+                return True
+            else:
+                sys.stdout.write("RefPath(%s): ManyRefsAllowed(%s)[%s]-> " % (self._id, len(referrers), fastRepr(at, maxLen = 1, strFactor = 30)))
+                print                
                 pass
                 pass
             pass
             pass
-
-        yield None
-        pass
+        return False
     pass
     pass
 
 
 
 
+
 """
 """
 from direct.showbase.ReferrerSearch import ReferrerSearch
 from direct.showbase.ReferrerSearch import ReferrerSearch
 door = simbase.air.doFind("DistributedBuildingDoorAI")
 door = simbase.air.doFind("DistributedBuildingDoorAI")