Ok. Lo que estaba buscando exactamente no parece existir. Entonces, encontré una solución, una solución para este problema.
En lugar de perfilar la memoria, voy a perfilar los objetos. De esta manera, podré ver cuántos objetos existen en un momento específico del programa. Para lograr mi objetivo, utilicé las metaclases con una modificación mínima al código ya existente.
La siguiente metaclase agrega una subrutina muy simple a las funciones __init__
y __del__
de la clase. La subrutina para __init__
aumenta el número de objetos con ese nombre de clase en uno y el __del__
disminuye en uno.
class ObjectProfilerMeta(type):
#Just set metaclass of a class to ObjectProfilerMeta to profile object
def __new__(cls, name, bases, attrs):
if name.startswith('None'):
return None
if "__init__" in attrs:
attrs["__init__"]=incAndCall(name,attrs["__init__"])
else:
attrs["__init__"]=incAndCall(name,dummyFunction)
if "__del__" in attrs:
attrs["__del__"]=decAndCall(name,attrs["__del__"])
else:
attrs["__del__"]=decAndCall(name,dummyFunction)
return super(ObjectProfilerMeta, cls).__new__(cls, name, bases, attrs)
def __init__(self, name, bases, attrs):
super(ObjectProfilerMeta, self).__init__(name, bases, attrs)
def __add__(self, other):
class AutoClass(self, other):
pass
return AutoClass
Las funciones incAndCall y decAndCall utilizan el uso de la variable global del módulo que existen.
counter={}
def incAndCall(name,func):
if name not in counter:
counter[name]=0
def f(*args,**kwargs):
counter[name]+=1
func(*args,**kwargs)
return f
def decAndCall(name,func):
if name not in counter:
counter[name]=0
def f(*args,**kwargs):
counter[name]-=1
func(*args,**kwargs)
return f
def dummyFunction(*args,**kwargs):
pass
La función dummyFunction es simplemente una solución muy simple. Estoy seguro de que hay formas mucho mejores de hacerlo.
Finalmente, siempre que quiera ver el número de objetos que existen, solo tiene que mirar el diccionario del contador. Un ejemplo;
>>> class A:
__metaclass__=ObjectProfilerMeta
def __init__(self):
pass
>>> class B:
__metaclass__=ObjectProfilerMeta
>>> l=[]
>>> for i in range(117):
l.append(A())
>>> for i in range(18):
l.append(B())
>>> counter
{'A': 117, 'B': 18}
>>> l.pop(15)
<__main__.A object at 0x01210CB0>
>>> counter
{'A': 116, 'B': 18}
>>> l=[]
>>> counter
{'A': 0, 'B': 0}
Espero que esto te ayude. Fue suficiente para mi caso.
¿Qué no te gusta de las soluciones en esas otras preguntas? – Falmarri
@Falmarri, estoy buscando un generador de perfiles de 'memoria'. El primero es principalmente un perfilador de CPU. El segundo solo funciona para un solo hilo. –
La característica principal de los hilos es que comparten memoria (a diferencia de los procesos). ¿Cómo espera perfilar diferentes estadísticas de memoria para hilos que comparten la misma memoria? – scoffey