Ok. Quello che stavo cercando esattamente non sembra esistere. Quindi, ho trovato una soluzione, una soluzione per questo problema.
Invece della memoria di profilazione, eseguirò il profilo degli oggetti. In questo modo, sarò in grado di vedere quanti oggetti esistono in un momento specifico nel programma. Per raggiungere il mio obiettivo, ho fatto uso di metaclassi con modifiche minime al codice già esistente.
Il seguente metaclasse aggiunge una subroutine molto semplice alle funzioni __init__
e __del__
della classe. La subroutine per __init__
aumenta di uno il numero di oggetti con quel nome di classe e lo __del__
diminuisce di 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
Le funzioni incAndCall e decAndCall utilizzano la variabile globale di utilizzo del modulo esistente.
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
Il dummyFunction è solo una soluzione molto semplice. Sono sicuro che ci sono modi molto migliori per farlo.
Infine, ogni volta che si desidera vedere il numero di oggetti esistenti, è sufficiente consultare il dizionario del contatore. Un esempio;
>>> 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}
Spero che questo ti aiuta. Era sufficiente per il mio caso.
Cosa non ti piace delle soluzioni in quelle altre domande? – Falmarri
@Falmarri, sto cercando un profiler 'memoria'. Il primo è principalmente un profilo della CPU. Il secondo funziona solo per un singolo thread. –
La caratteristica principale dei thread è che condividono la memoria (al contrario dei processi). Come ti aspetti di profilare diverse statistiche di memoria per i thread che condividono la stessa memoria? – scoffey