def _scheduleNextProfile(self): self._profileCounter += 1 self._timeElapsed = self._profileCounter * self._period #assert isInteger(self._timeElapsed) time = self._startTime + self._timeElapsed # vary the actual delay between profiles by a random amount to prevent interaction # with periodic events jitter = self._jitter if jitter is None: jitter = normalDistrib(-self._jitterMagnitude, self._jitterMagnitude) time += jitter else: time -= jitter jitter = None self._jitter = jitter sessionId = serialNum() session = taskMgr.getProfileSession('FrameProfile-%s' % sessionId) self._id2session[sessionId] = session taskMgr.profileFrames(num=1, session=session, callback=Functor(self._analyzeResults, sessionId)) # schedule the next profile delay = max(time - globalClock.getFrameTime(), 0.) self._task = taskMgr.doMethodLater(delay, self._scheduleNextProfileDoLater, 'FrameProfiler-%s' % serialNum())
def leakTask(task = None, leakTaskName = leakTaskName): base = getBase() taskMgr.add(nullTask, uniqueName(leakTaskName)) taskMgr.doMethodLater(1 << 31, nullDoLater, uniqueName(leakDoLaterName)) taskMgr.doMethodLater(10, leakTask, 'doLeakTask-%s' % serialNum()) if task: return task.done
def _setEnabled(self, enabled): if enabled: self.notify.info('frame profiler started') self._startTime = globalClock.getFrameTime() self._profileCounter = 0 self._jitter = None self._period2aggregateProfile = {} self._id2session = {} self._id2task = {} # don't profile process startup self._task = taskMgr.doMethodLater( self._period, self._scheduleNextProfileDoLater, 'FrameProfilerStart-%s' % serialNum()) else: self._task.remove() del self._task for session in self._period2aggregateProfile.values(): session.release() del self._period2aggregateProfile for task in self._id2task.values(): task.remove() del self._id2task for session in self._id2session.values(): session.release() del self._id2session self.notify.info('frame profiler stopped')
def __init__(self, name, firstCheckDelay = None): Job.__init__(self, name) self._serialNum = serialNum() self._findContainersJob = None self._checkContainersJob = None self._pruneContainersJob = None if firstCheckDelay is None: firstCheckDelay = 60.0 * 15.0 self._nextCheckDelay = firstCheckDelay / 2.0 self._checkDelayScale = config.GetFloat('leak-detector-check-delay-scale', 1.5) self._pruneTaskPeriod = config.GetFloat('leak-detector-prune-period', 60.0 * 30.0) self._id2ref = { } self._index2containerId2len = { } self._index2delay = { } if config.GetBool('leak-container', 0): _createContainerLeak() if config.GetBool('leak-tasks', 0): _createTaskLeak() ContainerLeakDetector.addPrivateObj(ContainerLeakDetector.PrivateIds) ContainerLeakDetector.addPrivateObj(self.__dict__) self.setPriority(Job.Priorities.Min) jobMgr.add(self)
def __init__(self, name, firstCheckDelay = None): Job.__init__(self, name) self._serialNum = serialNum() self._findContainersJob = None self._checkContainersJob = None self._pruneContainersJob = None if firstCheckDelay is None: firstCheckDelay = 60. * 15. # divide by two, since the first check just takes length measurements and # doesn't check for leaks self._nextCheckDelay = firstCheckDelay/2. self._checkDelayScale = config.GetFloat('leak-detector-check-delay-scale', 1.5) self._pruneTaskPeriod = config.GetFloat('leak-detector-prune-period', 60. * 30.) # main dict of id(container)->containerRef self._id2ref = {} # storage for results of check-container job self._index2containerId2len = {} self._index2delay = {} if config.GetBool('leak-container', 0): _createContainerLeak() if config.GetBool('leak-tasks', 0): _createTaskLeak() # don't check our own tables for leaks ContainerLeakDetector.addPrivateObj(ContainerLeakDetector.PrivateIds) ContainerLeakDetector.addPrivateObj(self.__dict__) self.setPriority(Job.Priorities.Min) jobMgr.add(self)
def leakTask(task=None, leakTaskName=leakTaskName): base = getBase() taskMgr.add(nullTask, uniqueName(leakTaskName)) taskMgr.doMethodLater(1 << 31, nullDoLater, uniqueName(leakDoLaterName)) taskMgr.doMethodLater(10, leakTask, 'doLeakTask-%s' % serialNum()) if task: return task.done
def leakContainer(task = None): base = getBase() if not hasattr(base, 'leakContainer'): base.leakContainer = { } class LeakKey: pass base.leakContainer[(LeakKey(),)] = { } if random.random() < 0.01: key = random.choice(base.leakContainer.keys()) ContainerLeakDetector.notify.debug('removing reference to leakContainer key %s so it will be garbage-collected' % safeRepr(key)) del base.leakContainer[key] taskMgr.doMethodLater(10, leakContainer, 'leakContainer-%s' % serialNum()) if task: return task.done
def leakContainer(task=None): base = getBase() if not hasattr(base, 'leakContainer'): base.leakContainer = {} # use tuples as keys since they can't be weakref'd, and use an instance # since it can't be repr/eval'd # that will force the leak detector to hold a normal 'non-weak' reference class LeakKey: pass base.leakContainer[(LeakKey(),)] = {} # test the non-weakref object reference handling if random.random() < .01: key = random.choice(list(base.leakContainer.keys())) ContainerLeakDetector.notify.debug( 'removing reference to leakContainer key %s so it will be garbage-collected' % safeRepr(key)) del base.leakContainer[key] taskMgr.doMethodLater(10, leakContainer, 'leakContainer-%s' % serialNum()) if task: return task.done
def leakContainer(task=None): base = getBase() if not hasattr(base, 'leakContainer'): base.leakContainer = {} # use tuples as keys since they can't be weakref'd, and use an instance # since it can't be repr/eval'd # that will force the leak detector to hold a normal 'non-weak' reference class LeakKey: pass base.leakContainer[(LeakKey(),)] = {} # test the non-weakref object reference handling if random.random() < .01: key = random.choice(base.leakContainer.keys()) ContainerLeakDetector.notify.debug( 'removing reference to leakContainer key %s so it will be garbage-collected' % safeRepr(key)) del base.leakContainer[key] taskMgr.doMethodLater(10, leakContainer, 'leakContainer-%s' % serialNum()) if task: return task.done
def _leakNode(self, task=None): self._render.attachNewNode('leakNode-%s' % serialNum()) taskMgr.doMethodLater(10, self._leakNode, self._leakTaskName)
def __init__(self, render): LeakDetector.__init__(self) self._render = render if ConfigVariableBool('leak-scene-graph', False): self._leakTaskName = 'leakNodes-%s' % serialNum() self._leakNode()