[Python] Garbage collection

Daniele Varrazzo piro a develer.com
Mar 30 Mar 2010 17:59:31 CEST


On Tue, 30 Mar 2010 15:42:34 +0200, Pietro Battiston <toobaz a email.it>
wrote:
> Il giorno mar, 30/03/2010 alle 13.04 +0200, Daniele Varrazzo ha
> scritto: 
>> On Tue, 30 Mar 2010 12:19:58 +0200, Pietro Battiston <toobaz a email.it>
>> wrote:
>> > Salve a tutti,
>> > 
>> > per quel che ne so, in python 2.5 e successivi il garbage collector
>> > dovrebbe esistere e funzionare, giusto?
>> > 
>> > Sapreste spiegarmi perché allora, se io faccio un import del seguente
>> > semplice modulo:
>> > 
>> >
>>
http://bazaar.launchpad.net/~tv-player-team/tv-player/GTK-release-0.3/annotate/head%3A/libradiotv/rai_XML.py
>> > 
>> > e poi do "del rai_XML", python continua ad occupare 50 MB?
>> 
>> Prima del gc c'e' il ref count: devi avere 0 riferimenti al tuo modulo
>> prima che abbia una chance di essere cancellato. Qualunque altro modulo
>> lo
>> importi aggiunge un riferimento. C'e' anche il riferimento in
sys.modules
>> come ti hanno gia' detto. Puoi sapere quanti sono i ref usando
>> sys.getrefcount(rai_XML): minimo otterrai 3 (il nome rai_XML, il
>> riferimento nella funzione sys.getrefcount e quello in sys.modules). Se
>> ce
>> ne sono di piu' allora il modulo non lo cavi via.
> 
> ... e infatti sono 4... ma non c'è un metodo per sapere da quali oggetti
> vengono i riferimenti?

Non che io sappia.


>> Quello che vuoi fare non e' robusto perché un modulo non è esattamente
>> un
>> oggetto normale, nel senso che non sai il sistema come lo usa. Se vuoi
>> davvero ripulire la memoria, cancella la struttura contenute dal modulo
>> che
>> occupa 50MB, non il modulo stesso.
> 
> Ho provato, ma senza successo...  la struttura che penso sia colpevole
> ("xmldoc", nel codice) ha effettivamente 93105 referenze... ma non ho
> idea di chi siano i colpevoli (ho provato a fare "del" di tutto...).

Forse la struttura parsata ha dei backlink dai nodi al parent o al root,
non conosco minidom.

Posso consigliarti questa "ricetta":
http://code.activestate.com/recipes/523004/ con cui puoi trovare i
riferimenti ciclici in oggetti python. Per usarla, prima dai un
gc.collect(), poi print_cycles(gc.garbage) per avere un report di chi tiene
in vita chi (questo trova solo i riferimenti circolari, non i riferimenti
normali ad albero, quindi non risponde alla tua domanda di prima, ma magari
leggendo com'è fatta la ricetta trovi un modo per fare anche quello).

Comunque, aiuterebbe *non di poco* se quello che stai facendo lo facessi
in una funzione anziché in variabili di modulo. Se in una funzione crei
l'albero, con quello generi il report e restituisci solo il report, alla
fine della funzione l'albero deve essere distrutto: se non lo fa allora è
un bug di qualcuno (in quel caso forse sono i riferimenti circolari a
tenere in vita le strutture e puoi saperlo con la ricetta di sopra). Se fai
tutto a livello di modulo, non sei sicuro di cancellare tutti i riferimenti
(ad ad esempio probabilmente le variabili che usi per i loop lo stanno
tenendo in vita) quindi il bug è tuo e non si accettano lamentele :)


-- 
Daniele Varrazzo - Develer S.r.l. 
http://www.develer.com


Maggiori informazioni sulla lista Python