From 9890d111c7f1b1c02552e94103fa6f712e3945ba Mon Sep 17 00:00:00 2001 From: Josh Wilson Date: Sat, 31 Jul 2010 06:52:20 +0000 Subject: [PATCH] optimized referrer search --- direct/src/showbase/ReferrerSearch.py | 281 +++++++++++++++----------- 1 file changed, 165 insertions(+), 116 deletions(-) diff --git a/direct/src/showbase/ReferrerSearch.py b/direct/src/showbase/ReferrerSearch.py index bf99e91f78..56bf8f38d3 100755 --- a/direct/src/showbase/ReferrerSearch.py +++ b/direct/src/showbase/ReferrerSearch.py @@ -5,10 +5,12 @@ from direct.showbase.PythonUtil import _getSafeReprNotify from direct.showbase.Job import Job class ReferrerSearch(Job): - def __init__(self, obj): + def __init__(self, obj, maxRefs = 100): Job.__init__(self, 'ReferrerSearch') self.obj = obj + self.maxRefs = maxRefs self.found = set() + self.depth = 0 def __call__(self): safeReprNotify = _getSafeReprNotify() @@ -27,28 +29,29 @@ class ReferrerSearch(Job): def run(self): safeReprNotify = _getSafeReprNotify() - info = safeReprNotify.getInfo() + self.info = safeReprNotify.getInfo() 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() for x in self.stepGenerator(0, [self.obj]): yield None pass - self.obj = None - pass - - safeReprNotify.setInfo(info) - yield Job.Done pass 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 - + + safeReprNotify = _getSafeReprNotify() + safeReprNotify.setInfo(self.info) + pass + + def __del__(self): + print 'ReferrerSearch garbage collected' def truncateAtNewLine(self, s): if s.find('\n') == -1: @@ -85,142 +88,188 @@ class ReferrerSearch(Job): def step(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: + if id(at) in self.found: # don't continue down this path - return + return - # Now we define our 'roots' - - # __builtins__ - if at is __builtins__: - sys.stdout.write("RefPath: __builtins__-> ") - 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 + # check for success + if (self.isAtRoot(at, path)): return - # any module scope - if inspect.ismodule(at): - sys.stdout.write("RefPath: Module(%s)-> " % (at.__name__)) - path = list(reversed(path)) - for x in xrange(len(path)-1): - sys.stdout.write(self.myrepr(path[x], path[x+1])) - pass - print - return - - # simbase - if at is simbase: - sys.stdout.write("RefPath: simbase-> ") - 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 - - # simbase.air - if at is simbase.air: - sys.stdout.write("RefPath: simbase.air-> ") - 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 - + # mark our progress after checking goal self.found.add(id(at)) - - referrers = gc.get_referrers(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() - if (ref != path): - self.step(depth + 1, path + [ref]) + self.depth+=1 + for x in self.stepGenerator(depth + 1, path + [ref]): + pass + self.depth-=1 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: + if id(at) in self.found: # don't continue down this path raise StopIteration - # Now we define our 'roots' - - # __builtins__ - if at is __builtins__: - sys.stdout.write("RefPath: __builtins__-> ") - 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 + # check for success + if (self.isAtRoot(at, path)): raise StopIteration - # any module scope - if inspect.ismodule(at): - sys.stdout.write("RefPath: Module(%s)-> " % (at.__name__)) - path = list(reversed(path)) - for x in xrange(len(path)-1): - sys.stdout.write(self.myrepr(path[x], path[x+1])) - pass - print - raise StopIteration - - # simbase - if at is simbase: - sys.stdout.write("RefPath: simbase-> ") - 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 - raise StopIteration - - # simbase.air - if at is simbase.air: - sys.stdout.write("RefPath: simbase.air-> ") - 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 - raise StopIteration - + # mark our progress after checking goal self.found.add(id(at)) - referrers = gc.get_referrers(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() - if (ref != path): - for x in self.stepGenerator(depth + 1, path + [ref]): - yield None + 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__ + if at is __builtins__: + sys.stdout.write("RefPath(%s): __builtins__-> " % self._id) + 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 + + # any module scope + if inspect.ismodule(at): + sys.stdout.write("RefPath(%s): Module(%s)-> " % (self._id, at.__name__)) + path = list(reversed(path)) + for x in xrange(len(path)-1): + sys.stdout.write(self.myrepr(path[x], path[x+1])) + pass + print + return True + + # any class scope + if inspect.isclass(at): + sys.stdout.write("RefPath(%s): Class(%s)-> " % (self._id, at.__name__)) + path = list(reversed(path)) + for x in xrange(len(path)-1): + sys.stdout.write(self.myrepr(path[x], path[x+1])) + pass + print + return True + + # simbase + if at is simbase: + sys.stdout.write("RefPath(%s): simbase-> " % self._id) + 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 + + # simbase.air + if at is simbase.air: + sys.stdout.write("RefPath(%s): simbase.air-> " % self._id) + 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 + + # messenger + if at is messenger: + sys.stdout.write("RefPath(%s): messenger-> " % self._id) + 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 + + # taskMgr + if at is taskMgr: + sys.stdout.write("RefPath(%s): taskMgr-> " % self._id) + 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 + + # 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.insert(0,0) + for x in xrange(len(path)-1): + sys.stdout.write(self.myrepr(path[x], path[x+1])) + pass + print + return True + pass + + 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 + return False pass + """ from direct.showbase.ReferrerSearch import ReferrerSearch door = simbase.air.doFind("DistributedBuildingDoorAI")