quicker discovery of LeakDetector objects

This commit is contained in:
Darren Ranalli 2007-04-18 01:01:57 +00:00
parent 09926188fd
commit 61550870cb
2 changed files with 49 additions and 14 deletions

View File

@ -265,6 +265,14 @@ class FindContainers(Job):
# set up the base containers, the ones that hold most objects # set up the base containers, the ones that hold most objects
ref = ContainerRef(Indirection(evalStr='__builtin__.__dict__')) ref = ContainerRef(Indirection(evalStr='__builtin__.__dict__'))
self._id2baseStartRef[id(__builtin__.__dict__)] = ref self._id2baseStartRef[id(__builtin__.__dict__)] = ref
# container for objects that want to make sure they are found by
# the object exploration algorithm, including objects that exist
# just to measure things such as C++ memory usage, scene graph size,
# framerate, etc. See LeakDetectors.py
if not hasattr(__builtin__, "leakDetectors"):
__builtin__.leakDetectors = {}
ref = ContainerRef(Indirection(evalStr='leakDetectors'))
self._id2baseStartRef[id(leakDetectors)] = ref
for i in self._addContainerGen(__builtin__.__dict__, ref): for i in self._addContainerGen(__builtin__.__dict__, ref):
pass pass
try: try:
@ -369,9 +377,9 @@ class FindContainers(Job):
def run(self): def run(self):
try: try:
# this toggles between the sets of start refs every time we start a new traversal # this yields a different set of start refs every time we start a new traversal
workingListSelector = loopGen([self._baseStartRefWorkingList, # force creation of a new workingListSelector inside the while loop right off the bat
self._discoveredStartRefWorkingList]) workingListSelector = nullGen()
# this holds the current step of the current traversal # this holds the current step of the current traversal
curObjRef = None curObjRef = None
while True: while True:
@ -381,7 +389,19 @@ class FindContainers(Job):
#import pdb;pdb.set_trace() #import pdb;pdb.set_trace()
if curObjRef is None: if curObjRef is None:
# choose an object to start a traversal from # choose an object to start a traversal from
startRefWorkingList = workingListSelector.next() try:
startRefWorkingList = workingListSelector.next()
except StopIteration:
# do relative # of traversals on each set based on how many refs it contains
baseLen = len(self._baseStartRefWorkingList.source)
discLen = len(self._discoveredStartRefWorkingList.source)
minLen = float(max(1, min(baseLen, discLen)))
# this will cut down the traversals of the larger set by 2/3
minLen *= 3.
workingListSelector = flywheel([self._baseStartRefWorkingList, self._discoveredStartRefWorkingList],
[baseLen/minLen, discLen/minLen])
yield None
continue
# grab the next start ref from this sequence and see if it's still valid # grab the next start ref from this sequence and see if it's still valid
while True: while True:
@ -396,12 +416,12 @@ class FindContainers(Job):
break break
# make a generator that yields containers a # of times that is # make a generator that yields containers a # of times that is
# proportional to their length # proportional to their length
for flywheel in makeFlywheelGen( for fw in makeFlywheelGen(
startRefWorkingList.source.values(), startRefWorkingList.source.values(),
countFunc=lambda x: self.getStartObjAffinity(x), countFunc=lambda x: self.getStartObjAffinity(x),
scale=.05): scale=.05):
yield None yield None
startRefWorkingList.refGen = flywheel startRefWorkingList.refGen = fw
if curObjRef is None: if curObjRef is None:
# this ref set is empty, choose another # this ref set is empty, choose another
# the base set should never be empty (__builtin__ etc.) # the base set should never be empty (__builtin__ etc.)
@ -540,8 +560,7 @@ class FindContainers(Job):
except Exception, e: except Exception, e:
print 'FindContainers job caught exception: %s' % e print 'FindContainers job caught exception: %s' % e
if __dev__: if __dev__:
#raise e raise
pass
yield Job.Done yield Job.Done
class CheckContainers(Job): class CheckContainers(Job):
@ -680,8 +699,7 @@ class CheckContainers(Job):
except Exception, e: except Exception, e:
print 'CheckContainers job caught exception: %s' % e print 'CheckContainers job caught exception: %s' % e
if __dev__: if __dev__:
#raise e raise
pass
yield Job.Done yield Job.Done
class PruneContainerRefs(Job): class PruneContainerRefs(Job):
@ -736,8 +754,7 @@ class PruneContainerRefs(Job):
except Exception, e: except Exception, e:
print 'PruneContainerRefs job caught exception: %s' % e print 'PruneContainerRefs job caught exception: %s' % e
if __dev__: if __dev__:
#raise e raise
pass
yield Job.Done yield Job.Done
class ContainerLeakDetector(Job): class ContainerLeakDetector(Job):

View File

@ -1,8 +1,21 @@
# objects that report different types of leaks to the ContainerLeakDetector # objects that report different types of leaks to the ContainerLeakDetector
class SceneGraphLeakDetector: import __builtin__
class LeakDetector:
def __init__(self):
# put this object just under __builtins__ where the
# ContainerLeakDetector will find it quickly
if not hasattr(__builtin__, "leakDetectors"):
__builtin__.leakDetectors = {}
leakDetectors[id(self)] = self
def destroy(self):
del leakDetectors[id(self)]
class SceneGraphLeakDetector(LeakDetector):
# is a scene graph leaking nodes? # is a scene graph leaking nodes?
def __init__(self, render): def __init__(self, render):
LeakDetector.__init__(self)
self._render = render self._render = render
if config.GetBool('leak-scene-graph', 0): if config.GetBool('leak-scene-graph', 0):
self._leakTaskName = 'leakNodes-%s' % serialNum() self._leakTaskName = 'leakNodes-%s' % serialNum()
@ -11,8 +24,13 @@ class SceneGraphLeakDetector:
if hasattr(self, '_leakTaskName'): if hasattr(self, '_leakTaskName'):
taskMgr.remove(self._leakTaskName) taskMgr.remove(self._leakTaskName)
del self._render del self._render
LeakDetector.destroy(self)
def __len__(self): def __len__(self):
return self._render.getNumDescendants() try:
# this will be available when the build server finishes
return self._render.countNumDescendants()
except:
return self._render.getNumDescendants()
def __repr__(self): def __repr__(self):
return 'SceneGraphLeakDetector(%s)' % self._render return 'SceneGraphLeakDetector(%s)' % self._render
def _leakNode(self, task=None): def _leakNode(self, task=None):