瀏覽代碼

use TaskThreaded to reduce AI CPU hit

Darren Ranalli 19 年之前
父節點
當前提交
968c71d5a5
共有 1 個文件被更改,包括 59 次插入20 次删除
  1. 59 20
      direct/src/showbase/GarbageReport.py

+ 59 - 20
direct/src/showbase/GarbageReport.py

@@ -1,6 +1,6 @@
 from direct.directnotify import DirectNotifyGlobal
 from direct.directnotify import DirectNotifyGlobal
 from direct.showbase import PythonUtil
 from direct.showbase import PythonUtil
-from direct.showbase.PythonUtil import POD
+from direct.showbase.TaskThreaded import TaskThreaded
 import gc
 import gc
 
 
 class FakeObject:
 class FakeObject:
@@ -12,7 +12,7 @@ def _createGarbage():
     a.other = b
     a.other = b
     b.other = a
     b.other = a
 
 
-class GarbageReport:
+class GarbageReport(TaskThreaded):
     """Detects leaked Python objects (via gc.collect()) and reports on garbage
     """Detects leaked Python objects (via gc.collect()) and reports on garbage
     items, garbage-to-garbage references, and garbage cycles.
     items, garbage-to-garbage references, and garbage cycles.
     If you just want to dump the report to the log, use GarbageLogger."""
     If you just want to dump the report to the log, use GarbageLogger."""
@@ -20,9 +20,23 @@ class GarbageReport:
 
 
     NotGarbage = 'NG'
     NotGarbage = 'NG'
 
 
-    def __init__(self, name=None, log=True, verbose=False, fullReport=False, findCycles=True):
+    def __init__(self, name, log=True, verbose=False, fullReport=False, findCycles=True,
+                 threaded=False, doneCallback=None):
         # if log is True, GarbageReport will self-destroy after logging
         # if log is True, GarbageReport will self-destroy after logging
         # if false, caller is responsible for calling destroy()
         # if false, caller is responsible for calling destroy()
+        # if threaded is True, processing will be performed over multiple frames
+        TaskThreaded.__init__(self, name, threaded)
+        # stick the arguments onto a ScratchPad so we can access them from the thread
+        # functions and delete them all at once
+        self._args = ScratchPad()
+        self._args.name = name
+        self._args.log = log
+        self._args.verbose = verbose
+        self._args.fullReport = fullReport
+        self._args.findCycles = findCycles
+        self._args.doneCallback = doneCallback
+
+        # do the garbage collection
         wasOn = PythonUtil.gcDebugOn()
         wasOn = PythonUtil.gcDebugOn()
         oldFlags = gc.get_debug()
         oldFlags = gc.get_debug()
         if not wasOn:
         if not wasOn:
@@ -37,14 +51,17 @@ class GarbageReport:
 
 
         self.numGarbage = len(self.garbage)
         self.numGarbage = len(self.garbage)
 
 
-        if verbose:
+        if self._args.verbose:
             self.notify.info('found %s garbage items' % self.numGarbage)
             self.notify.info('found %s garbage items' % self.numGarbage)
 
 
+        self.scheduleNext(self.T_getReferrers)
+    def T_getReferrers(self):
+
         # grab the referrers (pointing to garbage)
         # grab the referrers (pointing to garbage)
         self.referrersByReference = {}
         self.referrersByReference = {}
         self.referrersByNumber = {}
         self.referrersByNumber = {}
-        if fullReport:
-            if verbose:
+        if self._args.fullReport:
+            if self._args.verbose:
                 self.notify.info('getting referrers...')
                 self.notify.info('getting referrers...')
             # we need referents to detect cycles, but we don't need referrers
             # we need referents to detect cycles, but we don't need referrers
             for i in xrange(self.numGarbage):
             for i in xrange(self.numGarbage):
@@ -52,23 +69,32 @@ class GarbageReport:
                 self.referrersByNumber[i] = byNum
                 self.referrersByNumber[i] = byNum
                 self.referrersByReference[i] = byRef
                 self.referrersByReference[i] = byRef
 
 
+        self.scheduleNext(self.T_getReferents)
+    def T_getReferents(self):
+
         # grab the referents (pointed to by garbage)
         # grab the referents (pointed to by garbage)
         self.referentsByReference = {}
         self.referentsByReference = {}
         self.referentsByNumber = {}
         self.referentsByNumber = {}
-        if verbose:
+        if self._args.verbose:
             self.notify.info('getting referents...')
             self.notify.info('getting referents...')
         for i in xrange(self.numGarbage):
         for i in xrange(self.numGarbage):
             byNum, byRef = self._getReferents(self.garbage[i])
             byNum, byRef = self._getReferents(self.garbage[i])
             self.referentsByNumber[i] = byNum
             self.referentsByNumber[i] = byNum
             self.referentsByReference[i] = byRef
             self.referentsByReference[i] = byRef
 
 
+        self.scheduleNext(self.T_getCycles)
+    def T_getCycles(self):
+
         # find the cycles
         # find the cycles
-        if findCycles and self.numGarbage > 0:
-            if verbose:
+        if self._args.findCycles and self.numGarbage > 0:
+            if self._args.verbose:
                 self.notify.info('detecting cycles...')
                 self.notify.info('detecting cycles...')
             self.cycles = self._getCycles()
             self.cycles = self._getCycles()
 
 
-        s = '\n===== GarbageReport: \'%s\' (%s items) =====' % (name, self.numGarbage)
+        self.scheduleNext(self.T_createReport)
+    def T_createReport(self):
+
+        s = '\n===== GarbageReport: \'%s\' (%s items) =====' % (self._args.name, self.numGarbage)
         if self.numGarbage > 0:
         if self.numGarbage > 0:
             # log each individual item with a number in front of it
             # log each individual item with a number in front of it
             s += '\n\n===== Garbage Items ====='
             s += '\n\n===== Garbage Items ====='
@@ -81,13 +107,13 @@ class GarbageReport:
             for i in range(len(self.garbage)):
             for i in range(len(self.garbage)):
                 s += format % (i, type(self.garbage[i]), self.garbage[i])
                 s += format % (i, type(self.garbage[i]), self.garbage[i])
 
 
-            if findCycles:
+            if self._args.findCycles:
                 format = '\n%s'
                 format = '\n%s'
                 s += '\n\n===== Cycles ====='
                 s += '\n\n===== Cycles ====='
                 for cycle in self.cycles:
                 for cycle in self.cycles:
                     s += format % cycle
                     s += format % cycle
 
 
-            if fullReport:
+            if self._args.fullReport:
                 format = '\n%0' + '%s' % digits + 'i:%s'
                 format = '\n%0' + '%s' % digits + 'i:%s'
                 s += '\n\n===== Referrers By Number (what is referring to garbage item?) ====='
                 s += '\n\n===== Referrers By Number (what is referring to garbage item?) ====='
                 for i in xrange(self.numGarbage):
                 for i in xrange(self.numGarbage):
@@ -103,19 +129,21 @@ class GarbageReport:
                     s += format % (i, self.referentsByReference[i])
                     s += format % (i, self.referentsByReference[i])
 
 
         self._report = s
         self._report = s
-        if log:
-            self.notify.info(self._report)
 
 
-    def getNumItems(self):
-        return self.numGarbage
+        self.scheduleNext(self.T_printReport)
+    def T_printReport(self):
 
 
-    def getGarbage(self):
-        return self.garbage
+        if self._args.log:
+            self.notify.info(self._report)
 
 
-    def getReport(self):
-        return self._report
+        self.scheduleNext(self.T_completed)
+    def T_completed(self):
+
+        if self._args.doneCallback:
+            self._args.doneCallback(self)
 
 
     def destroy(self):
     def destroy(self):
+        del self._args
         del self.garbage
         del self.garbage
         del self.numGarbage
         del self.numGarbage
         del self.referrersByReference
         del self.referrersByReference
@@ -126,6 +154,15 @@ class GarbageReport:
             del self.cycles
             del self.cycles
         del self._report
         del self._report
 
 
+    def getNumItems(self):
+        return self.numGarbage
+
+    def getGarbage(self):
+        return self.garbage
+
+    def getReport(self):
+        return self._report
+
     def _getReferrers(self, obj):
     def _getReferrers(self, obj):
         # referrers (pointing to garbage)
         # referrers (pointing to garbage)
         # returns two lists, first by index into gc.garbage, second by
         # returns two lists, first by index into gc.garbage, second by
@@ -203,4 +240,6 @@ class GarbageLogger(GarbageReport):
     def __init__(self, *args, **kArgs):
     def __init__(self, *args, **kArgs):
         kArgs['log'] = True
         kArgs['log'] = True
         GarbageReport.__init__(self, *args, **kArgs)
         GarbageReport.__init__(self, *args, **kArgs)
+    def T_completed(self):
+        GarbageReport.T_completed(self)
         self.destroy()
         self.destroy()