mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
better timeslicing
This commit is contained in:
parent
01b6acdcfe
commit
301c6d9aea
@ -10,7 +10,8 @@ import gc
|
|||||||
class FakeObject:
|
class FakeObject:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _createGarbage():
|
def _createGarbage(num=1):
|
||||||
|
for i in xrange(num):
|
||||||
a = FakeObject()
|
a = FakeObject()
|
||||||
b = FakeObject()
|
b = FakeObject()
|
||||||
a.other = b
|
a.other = b
|
||||||
@ -79,36 +80,39 @@ class GarbageReport(Job):
|
|||||||
if self._args.verbose:
|
if self._args.verbose:
|
||||||
self.notify.info('getting referrers...')
|
self.notify.info('getting referrers...')
|
||||||
for i in xrange(self.numGarbage):
|
for i in xrange(self.numGarbage):
|
||||||
byNum, byRef = parent._getReferrers(self.garbage[i])
|
yield None
|
||||||
|
for result in self._getReferrers(self.garbage[i]):
|
||||||
|
yield None
|
||||||
|
byNum, byRef = result
|
||||||
self.referrersByNumber[i] = byNum
|
self.referrersByNumber[i] = byNum
|
||||||
self.referrersByReference[i] = byRef
|
self.referrersByReference[i] = byRef
|
||||||
if (not (i & 0x0F)):
|
|
||||||
yield None
|
|
||||||
|
|
||||||
# grab the referents (pointed to by garbage)
|
# grab the referents (pointed to by garbage)
|
||||||
if self.numGarbage > 0:
|
if self.numGarbage > 0:
|
||||||
if self._args.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])
|
yield None
|
||||||
|
for result in self._getReferents(self.garbage[i]):
|
||||||
|
yield None
|
||||||
|
byNum, byRef = result
|
||||||
self.referentsByNumber[i] = byNum
|
self.referentsByNumber[i] = byNum
|
||||||
self.referentsByReference[i] = byRef
|
self.referentsByReference[i] = byRef
|
||||||
if (not (i & 0x0F)):
|
|
||||||
yield None
|
|
||||||
|
|
||||||
# find the cycles
|
# find the cycles
|
||||||
if self._args.findCycles and self.numGarbage > 0:
|
if self._args.findCycles and self.numGarbage > 0:
|
||||||
if self._args.verbose:
|
if self._args.verbose:
|
||||||
self.notify.info('detecting cycles...')
|
self.notify.info('detecting cycles...')
|
||||||
for i in xrange(self.numGarbage):
|
for i in xrange(self.numGarbage):
|
||||||
newCycles = self._getCycles(i, self.cycleSets)
|
yield None
|
||||||
|
for newCycles in self._getCycles(i, self.cycleSets):
|
||||||
|
yield None
|
||||||
self.cycles.extend(newCycles)
|
self.cycles.extend(newCycles)
|
||||||
# if we're not doing a full report, add this cycle's IDs to the master set
|
# if we're not doing a full report, add this cycle's IDs to the master set
|
||||||
if not self._args.fullReport:
|
if not self._args.fullReport:
|
||||||
for cycle in newCycles:
|
for cycle in newCycles:
|
||||||
self.cycleIds.update(set(cycle))
|
|
||||||
if (not (i & 0x0F)):
|
|
||||||
yield None
|
yield None
|
||||||
|
self.cycleIds.update(set(cycle))
|
||||||
|
|
||||||
s = ['===== GarbageReport: \'%s\' (%s items) =====' % (
|
s = ['===== GarbageReport: \'%s\' (%s items) =====' % (
|
||||||
self._args.name, self.numGarbage)]
|
self._args.name, self.numGarbage)]
|
||||||
@ -130,12 +134,14 @@ class GarbageReport(Job):
|
|||||||
digits = 0
|
digits = 0
|
||||||
n = numGarbage
|
n = numGarbage
|
||||||
while n > 0:
|
while n > 0:
|
||||||
|
yield None
|
||||||
digits += 1
|
digits += 1
|
||||||
n /= 10
|
n /= 10
|
||||||
digits = digits
|
digits = digits
|
||||||
format = '%0' + '%s' % digits + 'i:%s \t%s'
|
format = '%0' + '%s' % digits + 'i:%s \t%s'
|
||||||
|
|
||||||
for i in xrange(numGarbage):
|
for i in xrange(numGarbage):
|
||||||
|
yield None
|
||||||
id = garbageIds[i]
|
id = garbageIds[i]
|
||||||
objStr = safeRepr(self.garbage[id])
|
objStr = safeRepr(self.garbage[id])
|
||||||
maxLen = 5000
|
maxLen = 5000
|
||||||
@ -143,47 +149,39 @@ class GarbageReport(Job):
|
|||||||
snip = '<SNIP>'
|
snip = '<SNIP>'
|
||||||
objStr = '%s%s' % (objStr[:(maxLen-len(snip))], snip)
|
objStr = '%s%s' % (objStr[:(maxLen-len(snip))], snip)
|
||||||
s.append(format % (id, itype(self.garbage[id]), objStr))
|
s.append(format % (id, itype(self.garbage[id]), objStr))
|
||||||
if (not (i & 0x7F)):
|
|
||||||
yield None
|
|
||||||
|
|
||||||
if self._args.findCycles:
|
if self._args.findCycles:
|
||||||
s.append('\n===== Garbage Cycles =====')
|
s.append('\n===== Garbage Cycles =====')
|
||||||
for i in xrange(len(self.cycles)):
|
for i in xrange(len(self.cycles)):
|
||||||
s.append('%s' % self.cycles[i])
|
|
||||||
if (not (i & 0x7F)):
|
|
||||||
yield None
|
yield None
|
||||||
|
s.append('%s' % self.cycles[i])
|
||||||
|
|
||||||
if self._args.fullReport:
|
if self._args.fullReport:
|
||||||
format = '%0' + '%s' % digits + 'i:%s'
|
format = '%0' + '%s' % digits + 'i:%s'
|
||||||
s.append('\n===== Referrers By Number (what is referring to garbage item?) =====')
|
s.append('\n===== Referrers By Number (what is referring to garbage item?) =====')
|
||||||
for i in xrange(numGarbage):
|
for i in xrange(numGarbage):
|
||||||
s.append(format % (i, self.referrersByNumber[i]))
|
|
||||||
if (not (i & 0x7F)):
|
|
||||||
yield None
|
yield None
|
||||||
|
s.append(format % (i, self.referrersByNumber[i]))
|
||||||
s.append('\n===== Referents By Number (what is garbage item referring to?) =====')
|
s.append('\n===== Referents By Number (what is garbage item referring to?) =====')
|
||||||
for i in xrange(numGarbage):
|
for i in xrange(numGarbage):
|
||||||
s.append(format % (i, self.referentsByNumber[i]))
|
|
||||||
if (not (i & 0x7F)):
|
|
||||||
yield None
|
yield None
|
||||||
|
s.append(format % (i, self.referentsByNumber[i]))
|
||||||
s.append('\n===== Referrers (what is referring to garbage item?) =====')
|
s.append('\n===== Referrers (what is referring to garbage item?) =====')
|
||||||
for i in xrange(numGarbage):
|
for i in xrange(numGarbage):
|
||||||
s.append(format % (i, self.referrersByReference[i]))
|
|
||||||
if (not (i & 0x7F)):
|
|
||||||
yield None
|
yield None
|
||||||
|
s.append(format % (i, self.referrersByReference[i]))
|
||||||
s.append('\n===== Referents (what is garbage item referring to?) =====')
|
s.append('\n===== Referents (what is garbage item referring to?) =====')
|
||||||
for i in xrange(numGarbage):
|
for i in xrange(numGarbage):
|
||||||
s.append(format % (i, self.referentsByReference[i]))
|
|
||||||
if (not (i & 0x7F)):
|
|
||||||
yield None
|
yield None
|
||||||
|
s.append(format % (i, self.referentsByReference[i]))
|
||||||
|
|
||||||
self._report = s
|
self._report = s
|
||||||
|
|
||||||
if self._args.log:
|
if self._args.log:
|
||||||
self.printingBegin()
|
self.printingBegin()
|
||||||
for i in xrange(len(self._report)):
|
for i in xrange(len(self._report)):
|
||||||
print self._report[i]
|
|
||||||
if (not (i & 0x3F)):
|
|
||||||
yield None
|
yield None
|
||||||
|
print self._report[i]
|
||||||
# add an extra line at the end for readability
|
# add an extra line at the end for readability
|
||||||
if self.numGarbage > 0:
|
if self.numGarbage > 0:
|
||||||
print ''
|
print ''
|
||||||
@ -232,35 +230,43 @@ class GarbageReport(Job):
|
|||||||
# 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
|
||||||
# direct reference
|
# direct reference
|
||||||
|
yield None
|
||||||
byRef = gc.get_referrers(obj)
|
byRef = gc.get_referrers(obj)
|
||||||
|
yield None
|
||||||
# look to see if each referrer is another garbage item
|
# look to see if each referrer is another garbage item
|
||||||
byNum = []
|
byNum = []
|
||||||
for referrer in byRef:
|
for referrer in byRef:
|
||||||
|
yield None
|
||||||
try:
|
try:
|
||||||
num = self.garbage.index(referrer)
|
num = self.garbage.index(referrer)
|
||||||
byNum.append(num)
|
byNum.append(num)
|
||||||
except:
|
except:
|
||||||
#num = GarbageReport.NotGarbage
|
#num = GarbageReport.NotGarbage
|
||||||
pass
|
pass
|
||||||
return byNum, byRef
|
yield byNum, byRef
|
||||||
|
|
||||||
def _getReferents(self, obj):
|
def _getReferents(self, obj):
|
||||||
|
# TODO: make this a generator
|
||||||
# referents (pointed to by garbage)
|
# referents (pointed to by garbage)
|
||||||
# returns two lists, first by index into gc.garbage, second by
|
# returns two lists, first by index into gc.garbage, second by
|
||||||
# direct reference
|
# direct reference
|
||||||
|
yield None
|
||||||
byRef = gc.get_referents(obj)
|
byRef = gc.get_referents(obj)
|
||||||
|
yield None
|
||||||
# look to see if each referent is another garbage item
|
# look to see if each referent is another garbage item
|
||||||
byNum = []
|
byNum = []
|
||||||
for referent in byRef:
|
for referent in byRef:
|
||||||
|
yield None
|
||||||
try:
|
try:
|
||||||
num = self.garbage.index(referent)
|
num = self.garbage.index(referent)
|
||||||
byNum.append(num)
|
byNum.append(num)
|
||||||
except:
|
except:
|
||||||
#num = GarbageReport.NotGarbage
|
#num = GarbageReport.NotGarbage
|
||||||
pass
|
pass
|
||||||
return byNum, byRef
|
yield byNum, byRef
|
||||||
|
|
||||||
def _getCycles(self, index, cycleSets=None):
|
def _getCycles(self, index, cycleSets=None):
|
||||||
|
# TODO: make this a generator
|
||||||
# detect garbage cycles for a particular item of garbage
|
# detect garbage cycles for a particular item of garbage
|
||||||
assert self.notify.debugCall()
|
assert self.notify.debugCall()
|
||||||
# returns list of lists, sublists are garbage reference cycles
|
# returns list of lists, sublists are garbage reference cycles
|
||||||
@ -272,6 +278,7 @@ class GarbageReport(Job):
|
|||||||
rootId = index
|
rootId = index
|
||||||
stateStack.push(([rootId], rootId, 0))
|
stateStack.push(([rootId], rootId, 0))
|
||||||
while True:
|
while True:
|
||||||
|
yield None
|
||||||
if len(stateStack) == 0:
|
if len(stateStack) == 0:
|
||||||
break
|
break
|
||||||
candidateCycle, curId, resumeIndex = stateStack.pop()
|
candidateCycle, curId, resumeIndex = stateStack.pop()
|
||||||
@ -279,6 +286,7 @@ class GarbageReport(Job):
|
|||||||
print 'restart: %s root=%s cur=%s resume=%s' % (
|
print 'restart: %s root=%s cur=%s resume=%s' % (
|
||||||
candidateCycle, rootId, curId, resumeIndex)
|
candidateCycle, rootId, curId, resumeIndex)
|
||||||
for index in xrange(resumeIndex, len(self.referentsByNumber[curId])):
|
for index in xrange(resumeIndex, len(self.referentsByNumber[curId])):
|
||||||
|
yield None
|
||||||
refId = self.referentsByNumber[curId][index]
|
refId = self.referentsByNumber[curId][index]
|
||||||
if self.notify.getDebug():
|
if self.notify.getDebug():
|
||||||
print ' : %s -> %s' % (curId, refId)
|
print ' : %s -> %s' % (curId, refId)
|
||||||
@ -298,7 +306,7 @@ class GarbageReport(Job):
|
|||||||
stateStack.push((list(candidateCycle), curId, index+1))
|
stateStack.push((list(candidateCycle), curId, index+1))
|
||||||
stateStack.push((list(candidateCycle) + [refId], refId, 0))
|
stateStack.push((list(candidateCycle) + [refId], refId, 0))
|
||||||
break
|
break
|
||||||
return cycles
|
yield cycles
|
||||||
|
|
||||||
class GarbageLogger(GarbageReport):
|
class GarbageLogger(GarbageReport):
|
||||||
"""If you just want to log the current garbage to the log file, make
|
"""If you just want to log the current garbage to the log file, make
|
||||||
|
Loading…
x
Reference in New Issue
Block a user