mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 02:15:43 -04:00
optimized referrer search
This commit is contained in:
parent
55955862aa
commit
9890d111c7
@ -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,140 +88,186 @@ class ReferrerSearch(Job):
|
|||||||
def step(self, depth, path):
|
def step(self, depth, path):
|
||||||
at = path[-1]
|
at = path[-1]
|
||||||
|
|
||||||
if inspect.isframe(at) or \
|
if id(at) in self.found:
|
||||||
(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
|
# don't continue down this path
|
||||||
return
|
return
|
||||||
|
|
||||||
# Now we define our 'roots'
|
# check for success
|
||||||
|
if (self.isAtRoot(at, path)):
|
||||||
# __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
|
|
||||||
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
|
return
|
||||||
|
|
||||||
|
# mark our progress after checking goal
|
||||||
self.found.add(id(at))
|
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):
|
while(referrers):
|
||||||
ref = referrers.pop()
|
ref = referrers.pop()
|
||||||
if (ref != path):
|
self.depth+=1
|
||||||
self.step(depth + 1, path + [ref])
|
for x in self.stepGenerator(depth + 1, path + [ref]):
|
||||||
pass
|
pass
|
||||||
|
self.depth-=1
|
||||||
pass
|
pass
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def stepGenerator(self, depth, path):
|
def stepGenerator(self, depth, path):
|
||||||
at = path[-1]
|
at = path[-1]
|
||||||
|
|
||||||
if inspect.isframe(at) or \
|
if id(at) in self.found:
|
||||||
(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
|
# don't continue down this path
|
||||||
raise StopIteration
|
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'
|
# 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
|
||||||
raise StopIteration
|
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
|
||||||
raise StopIteration
|
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
|
# simbase
|
||||||
if at is simbase:
|
if at is simbase:
|
||||||
sys.stdout.write("RefPath: 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
|
||||||
raise StopIteration
|
return True
|
||||||
|
|
||||||
# simbase.air
|
# simbase.air
|
||||||
if at is simbase.air:
|
if at is simbase.air:
|
||||||
sys.stdout.write("RefPath: 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
|
return True
|
||||||
|
|
||||||
self.found.add(id(at))
|
# messenger
|
||||||
|
if at is messenger:
|
||||||
referrers = gc.get_referrers(at)
|
sys.stdout.write("RefPath(%s): messenger-> " % self._id)
|
||||||
while(referrers):
|
path = list(reversed(path))
|
||||||
ref = referrers.pop()
|
path.insert(0,0)
|
||||||
if (ref != path):
|
for x in xrange(len(path)-1):
|
||||||
for x in self.stepGenerator(depth + 1, path + [ref]):
|
sys.stdout.write(self.myrepr(path[x], path[x+1]))
|
||||||
yield None
|
|
||||||
pass
|
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
|
pass
|
||||||
|
|
||||||
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
|
||||||
|
return False
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user