2010-01-22 10 views
19

Sono stato sorpreso dal fatto che sys.getsizeof(10000*[x]) è 40036 indipendentemente da x: 0, "a", 1000 * "a", {}.
Esiste uno deep_getsizeof che considera correttamente gli elementi che condividono la memoria?
(La domanda veniva da guardando le tabelle del database in memoria come gamma (1000000) -> nomi di provincia: elenco o dict?)
(Python 2.6.4 è su un ppc mac.)Python fornisce una lista completa di contenuti?

Aggiunto: 10000 * ["Mississippi"] è 10000 puntatori a un "Mississippi", come hanno sottolineato diverse persone. Prova questo:

nstates = [AlabamatoWyoming() for j in xrange(N)] 

dove AlabamatoWyoming() -> una stringa "Alabama" .. "Wyoming". Cosa sono deep_getsizeof (nstates)?
(Come possiamo dire

  • una corretta deep_getsizeof:? Difficile, ~ tracciante gc
  • stima dal totale vm
  • all'interno la conoscenza della realizzazione di pitone
  • indovinare

. Aggiunto 25jan: vedi anche when-does-python-allocate-new-memory-for-identical-strings

risposta

5

Date un'occhiata al guppy/heapy; Non ho giocato troppo con me stesso, ma alcuni dei miei colleghi l'hanno usato per il profiling della memoria con buoni risultati.

La documentazione potrebbe essere migliore, ma this howto fa un lavoro decente di spiegare i concetti di base.

+0

Grazie Pär, ci proverò; mostra quanto sia difficile il problema. Qualcuno dei tuoi colleghi ha una breve nota sul salvataggio della memoria in Python, che risponderebbe ad es. range (1000000) -> province name: lista o dict? – denis

+1

link morto lì – MohamedEzz

14

10000 * [x] produrrà un elenco di 10000 volte lo stesso oggetto, quindi la dimensione di è in realtà più vicina alla correzione di quanto si pensi. Tuttavia, una dimensione profonda è molto problematica perché è impossibile dire a Python quando si desidera interrompere la misurazione. Ogni oggetto fa riferimento a un oggetto tipo. Dovrebbe essere contato il tipo oggetto? Cosa succede se il riferimento all'oggetto type è l'ultimo, quindi se si eliminava l'oggetto anche il typeobject andava via? Che dire se ci sono più oggetti (diversi) nella lista si riferiscono allo stesso oggetto stringa? Dovrebbe essere contato una volta o più volte?

In breve, ottenendo la dimensione di una struttura di dati è molto complicato, e non dovrebbe mai sono stati aggiunti sys.getsizeof(): S

+0

+1 è necessario definire dove fermarsi per eventuali oggetti profondi. Vuoi segnalare la memoria condivisa da altre parti del codice? Quindi questo è quasi tutto, dal momento che ha un riferimento a 'oggetto'. – nosklo

5

Se la lista sta tenendo solo gli oggetti con la stessa lunghezza si potrebbe ottenere un facendo questo numero di stima più accurato

def getSize(array): 
    return sys.getsizeof(array) + len(array) * sys.getsizeof(array[0]) 

Ovviamente non funzionerà altrettanto bene per le stringhe con lunghezza variabile.

Se si desidera calcolare solo la dimensione per il debug o durante lo sviluppo e non si cura delle prestazioni, è possibile scorrere su tutti gli elementi in modo ricorsivo e calcolare la dimensione totale. Si noti che questa soluzione non gestirà più riferimenti allo stesso oggetto correttamente.

0

mylist = 10000 * [x] significa creare un elenco di dimensioni 10000 con 10000 riferimenti a oggetto x.

Oggetto x è non copiato - ne esiste solo uno in memoria !!!

Quindi, per usare getsizeof, sarebbe: sys.getsizeof(mylist) + sys.getsizeof(x)

+0

Questo non è il caso per i tipi immutabili, sys.getsizeof (range (1000)) restituisce la stessa dimensione di sys.getsizeof ([0] * 1000) –

+0

@Nadia Alramli: Esattamente il mio punto - entrambi i vostri esempi stanno eseguendo 'sys. getsizeof' su un elenco di 1000 elementi: non importa quali oggetti sono, quindi restituiranno le stesse dimensioni. – nosklo

Problemi correlati