From b36dc682a33414afdf74095f233740c1a929c2ad Mon Sep 17 00:00:00 2001 From: Darren Ranalli Date: Mon, 22 Dec 2008 21:46:00 +0000 Subject: [PATCH] pulled garbage collect frequency reduction code from 1_0_14 --- .../src/distributed/ConnectionRepository.py | 47 +++++++++++++++++++ direct/src/showbase/ShowBase.py | 27 +---------- 2 files changed, 48 insertions(+), 26 deletions(-) diff --git a/direct/src/distributed/ConnectionRepository.py b/direct/src/distributed/ConnectionRepository.py index 29c359c8b7..caa7aca10f 100644 --- a/direct/src/distributed/ConnectionRepository.py +++ b/direct/src/distributed/ConnectionRepository.py @@ -26,6 +26,10 @@ class ConnectionRepository( CM_NET=1 CM_NATIVE=2 + gcNotify = directNotify.newCategory("GarbageCollect") + + GarbageCollectTaskName = "allowGarbageCollect" + GarbageThresholdTaskName = "adjustGarbageCollectThreshold" def __init__(self, connectMethod, config, hasOwnerView=False): assert self.notify.debugCall() @@ -107,6 +111,45 @@ class ConnectionRepository( # garbage collection CPU usage is O(n), n = number of Python objects gc.set_debug(gc.DEBUG_SAVEALL) + if self.config.GetBool('want-garbage-collect-task', 1): + # manual garbage-collect task + taskMgr.add(self._garbageCollect, self.GarbageCollectTaskName, 200) + # periodically increase gc threshold if there is no garbage + taskMgr.doMethodLater(self.config.GetFloat('garbage-threshold-adjust-delay', 15 * 60.), + self._adjustGcThreshold, self.GarbageThresholdTaskName) + + self._gcDefaultThreshold = gc.get_threshold() + + def _garbageCollect(self, task=None): + # allow a collect + # enable automatic garbage collection + gc.enable() + # creating an object with gc enabled causes garbage collection to trigger if appropriate + gct = GCTrigger() + # disable the automatic garbage collect during the rest of the frame + gc.disable() + return Task.cont + + def _adjustGcThreshold(self, task): + # do an unconditional collect to make sure gc.garbage has a chance to be + # populated before we start increasing the auto-collect threshold + gc.collect() + if len(gc.garbage) == 0: + self.gcNotify.debug('no garbage found, doubling gc threshold') + a, b, c = gc.get_threshold() + gc.set_threshold(min(a * 2, 1 << 30), b, c) + + task.delayTime = task.delayTime * 2 + retVal = Task.again + + else: + self.gcNotify.warning('garbage found, reverting gc threshold') + # the process is producing garbage, stick to the default collection threshold + gc.set_threshold(*self._gcDefaultThreshold) + retVal = Task.done + + return retVal + def generateGlobalObject(self, doId, dcname, values=None): def applyFieldValues(distObj, dclass, values): for i in range(dclass.getNumInheritedFields()): @@ -583,3 +626,7 @@ class ConnectionRepository( if self.networkPlugPulled(): self.notify.info('*** RESTORING SIMULATED PULLED-NETWORK-PLUG ***') self.setSimulatedDisconnect(0) + +class GCTrigger: + # used to trigger garbage collection + pass diff --git a/direct/src/showbase/ShowBase.py b/direct/src/showbase/ShowBase.py index 57f3228897..206daeb68d 100644 --- a/direct/src/showbase/ShowBase.py +++ b/direct/src/showbase/ShowBase.py @@ -54,8 +54,6 @@ class ShowBase(DirectObject.DirectObject): notify = directNotify.newCategory("ShowBase") - GarbageCollectTaskName = "allowGarbageCollect" - def __init__(self): __builtin__.__dev__ = config.GetBool('want-dev', 0) if config.GetBool('want-variable-dump', not __dev__): @@ -367,10 +365,6 @@ class ShowBase(DirectObject.DirectObject): if self.windowType != 'none': self.__doStartDirect() - if config.GetBool('want-garbage-collect-task', 1): - # manual garbage-collect task - taskMgr.add(self._garbageCollect, self.GarbageCollectTaskName, 200) - taskMgr.finalInit() # Start IGLOOP @@ -2307,26 +2301,7 @@ class ShowBase(DirectObject.DirectObject): self.startDirect(fWantDirect = fDirect, fWantTk = fTk, fWantWx = fWx) def run(self): - try: - self.taskMgr.run() - except: - # make sure gc is enabled when we break out to the prompt - gc.enable() - else: - gc.enable() - - def _garbageCollect(self, task=None): - # enable automatic garbage collection - gc.enable() - # creating an object with gc enabled causes garbage collection to trigger if appropriate - gct = GCTrigger() - # disable the automatic garbage collect during the rest of the frame - gc.disable() - return Task.cont - -class GCTrigger: - # used to trigger garbage collection - pass + self.taskMgr.run() # A class to encapsulate information necessary for multiwindow support.