optimized referrer search

This commit is contained in:
Josh Wilson 2010-07-31 06:52:20 +00:00
parent 55955862aa
commit 9890d111c7

View File

@ -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")