mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
memory usage optimization
This commit is contained in:
parent
ee7154a9c5
commit
2677e77fb7
@ -157,21 +157,18 @@ class ObjectRef:
|
|||||||
|
|
||||||
def __init__(self, indirection, objId, other=None):
|
def __init__(self, indirection, objId, other=None):
|
||||||
self._indirections = []
|
self._indirections = []
|
||||||
# this is a cache of the ids of our component objects
|
|
||||||
self._objIds = set()
|
|
||||||
# are we building off of an existing ref?
|
# are we building off of an existing ref?
|
||||||
if other is not None:
|
if other is not None:
|
||||||
self._objIds = set(other._objIds)
|
|
||||||
for ind in other._indirections:
|
for ind in other._indirections:
|
||||||
self._indirections.append(ind)
|
self._indirections.append(ind)
|
||||||
self._indirections.append(indirection)
|
|
||||||
|
|
||||||
# make sure we're not storing a reference to the actual object,
|
# make sure we're not storing a reference to the actual object,
|
||||||
# that could cause a memory leak
|
# that could cause a memory leak
|
||||||
assert type(objId) in (types.IntType, types.LongType)
|
assert type(objId) in (types.IntType, types.LongType)
|
||||||
# prevent cycles (i.e. base.loader.base.loader)
|
# prevent cycles (i.e. base.loader.base.loader)
|
||||||
assert objId not in self._objIds
|
assert not self.goesThrough(objId=objId)
|
||||||
self._objIds.add(objId)
|
|
||||||
|
self._indirections.append(indirection)
|
||||||
|
|
||||||
# make sure our indirections don't get destroyed while we're using them
|
# make sure our indirections don't get destroyed while we're using them
|
||||||
for ind in self._indirections:
|
for ind in self._indirections:
|
||||||
@ -186,12 +183,49 @@ class ObjectRef:
|
|||||||
def getNumIndirections(self):
|
def getNumIndirections(self):
|
||||||
return len(self._indirections)
|
return len(self._indirections)
|
||||||
|
|
||||||
def goesThrough(self, obj):
|
def goesThroughGen(self, obj=None, objId=None):
|
||||||
|
if obj is None:
|
||||||
|
assert type(objId) in (types.IntType, types.LongType)
|
||||||
|
else:
|
||||||
|
objId = id(obj)
|
||||||
|
o = None
|
||||||
|
evalStr = ''
|
||||||
|
curObj = None
|
||||||
|
# make sure the indirections don't go away on us
|
||||||
|
indirections = self._indirections
|
||||||
|
for indirection in indirections:
|
||||||
|
yield None
|
||||||
|
indirection.acquire()
|
||||||
|
for indirection in indirections:
|
||||||
|
yield None
|
||||||
|
if not indirection.isDictKey():
|
||||||
|
# build up a string to be eval'd
|
||||||
|
evalStr += indirection.getString()
|
||||||
|
else:
|
||||||
|
curObj = self._getContainerByEval(evalStr, curObj=curObj)
|
||||||
|
if curObj is None:
|
||||||
|
raise FailedEval(evalStr)
|
||||||
|
# try to look up this key in the curObj dictionary
|
||||||
|
curObj = indirection.dereferenceDictKey(curObj)
|
||||||
|
evalStr = ''
|
||||||
|
yield None
|
||||||
|
o = self._getContainerByEval(evalStr, curObj=curObj)
|
||||||
|
if id(o) == objId:
|
||||||
|
break
|
||||||
|
for indirection in indirections:
|
||||||
|
yield None
|
||||||
|
indirection.release()
|
||||||
|
|
||||||
|
yield id(o) == objId
|
||||||
|
|
||||||
|
def goesThrough(self, obj=None, objId=None):
|
||||||
# since we cache the ids involved in this reference,
|
# since we cache the ids involved in this reference,
|
||||||
# this isn't perfect, for example if base.myObject is reassigned
|
# this isn't perfect, for example if base.myObject is reassigned
|
||||||
# to a different object after this Ref was created this would return
|
# to a different object after this Ref was created this would return
|
||||||
# false, allowing a ref to base.myObject.otherObject.myObject
|
# false, allowing a ref to base.myObject.otherObject.myObject
|
||||||
return id(obj) in self._objIds
|
for goesThrough in self.goesThroughGen(obj=obj, objId=objId):
|
||||||
|
pass
|
||||||
|
return goesThrough
|
||||||
|
|
||||||
def _getContainerByEval(self, evalStr, curObj=None):
|
def _getContainerByEval(self, evalStr, curObj=None):
|
||||||
if curObj is not None:
|
if curObj is not None:
|
||||||
@ -207,7 +241,9 @@ class ObjectRef:
|
|||||||
container = eval(evalStr)
|
container = eval(evalStr)
|
||||||
except NameError, ne:
|
except NameError, ne:
|
||||||
return None
|
return None
|
||||||
except AttributeError, ne:
|
except AttributeError, ae:
|
||||||
|
return None
|
||||||
|
except KeyError, ke:
|
||||||
return None
|
return None
|
||||||
return container
|
return container
|
||||||
|
|
||||||
@ -510,7 +546,9 @@ class FindContainers(Job):
|
|||||||
notDeadEnd = not self._isDeadEnd(child)
|
notDeadEnd = not self._isDeadEnd(child)
|
||||||
if hasLength or notDeadEnd:
|
if hasLength or notDeadEnd:
|
||||||
# prevent cycles in the references (i.e. base.loader.base)
|
# prevent cycles in the references (i.e. base.loader.base)
|
||||||
if not parentObjRef.goesThrough(child):
|
for goesThrough in parentObjRef.goesThroughGen(child):
|
||||||
|
pass
|
||||||
|
if not goesThrough:
|
||||||
objRef = ObjectRef(Indirection(evalStr='.__dict__'),
|
objRef = ObjectRef(Indirection(evalStr='.__dict__'),
|
||||||
id(child), parentObjRef)
|
id(child), parentObjRef)
|
||||||
yield None
|
yield None
|
||||||
@ -546,7 +584,9 @@ class FindContainers(Job):
|
|||||||
notDeadEnd = not self._isDeadEnd(attr, key)
|
notDeadEnd = not self._isDeadEnd(attr, key)
|
||||||
if hasLength or notDeadEnd:
|
if hasLength or notDeadEnd:
|
||||||
# prevent cycles in the references (i.e. base.loader.base)
|
# prevent cycles in the references (i.e. base.loader.base)
|
||||||
if not parentObjRef.goesThrough(curObj[key]):
|
for goesThrough in parentObjRef.goesThroughGen(curObj[key]):
|
||||||
|
pass
|
||||||
|
if not goesThrough:
|
||||||
if curObj is __builtin__.__dict__:
|
if curObj is __builtin__.__dict__:
|
||||||
objRef = ObjectRef(Indirection(evalStr='%s' % key),
|
objRef = ObjectRef(Indirection(evalStr='%s' % key),
|
||||||
id(curObj[key]))
|
id(curObj[key]))
|
||||||
@ -595,7 +635,9 @@ class FindContainers(Job):
|
|||||||
notDeadEnd = not self._isDeadEnd(attr)
|
notDeadEnd = not self._isDeadEnd(attr)
|
||||||
if hasLength or notDeadEnd:
|
if hasLength or notDeadEnd:
|
||||||
# prevent cycles in the references (i.e. base.loader.base)
|
# prevent cycles in the references (i.e. base.loader.base)
|
||||||
if not parentObjRef.goesThrough(curObj[index]):
|
for goesThrough in parentObjRef.goesThrough(curObj[index]):
|
||||||
|
pass
|
||||||
|
if not goesThrough:
|
||||||
objRef = ObjectRef(Indirection(evalStr='[%s]' % index),
|
objRef = ObjectRef(Indirection(evalStr='[%s]' % index),
|
||||||
id(curObj[index]), parentObjRef)
|
id(curObj[index]), parentObjRef)
|
||||||
yield None
|
yield None
|
||||||
|
Loading…
x
Reference in New Issue
Block a user