2010-06-21 21 views
5

Il programma che ho scritto memorizza una grande quantità di dati nei dizionari. Nello specifico, sto creando 1588 istanze di una classe, ognuna delle quali contiene 15 dizionari con 1500 float per i mapping mobili. Questo processo ha utilizzato abbastanza velocemente i 2 GB di memoria sul mio laptop (inizio a scrivere per passare alla millesima istanza della classe).Utilizzo della memoria Python: quale dei miei oggetti sta registrando più memoria?

La mia domanda è: quale delle seguenti operazioni sta esaurendo la memoria?

  • 34 milioni di coppie di galleggianti?
  • Il sovraccarico di 22.500 dizionari?
  • l'overhead di 1500 classi?

Per me sembra che il maiale della memoria debba essere l'enorme numero di numeri in virgola mobile che sto tenendo in memoria. Tuttavia, se quello che ho letto finora è corretto, ognuno dei miei numeri in virgola mobile occupa 16 byte. Dato che ho 34 milioni di paia, questo dovrebbe essere di circa 108 milioni di byte, che dovrebbe essere di poco più di un gigabyte.

C'è qualcosa che non sto prendendo in considerazione qui?

risposta

7

I galleggianti fanno prendere 16 byte a testa, e un dict con 1500 voci circa 100k:

>> sys.getsizeof(1.0) 
16 
>>> d = dict.fromkeys((float(i) for i in range(1500)), 2.0) 
>>> sys.getsizeof(d) 
98444 

così i 22.500 dicts prendono più di 2 GB da soli, il 68 milioni galleggia un'altra GB o giù di lì. Non sei sicuro di come calcoli 68 milioni di volte 16 uguali solo a 100M - potresti aver perso uno zero da qualche parte.

La classe stessa occupa una quantità trascurabile e 1500 istanze (al netto degli oggetti a cui si riferiscono, naturalmente, proprio come getsizeof ci dà tali importi netti per i dict) non molto più di un piccolo dict ciascuno, quindi , questo non è il problema. Cioè .:

>>> sys.getsizeof(Sic) 
452 
>>> sys.getsizeof(Sic()) 
32 
>>> sys.getsizeof(Sic().__dict__) 
524 

452 per la classe, (524 + 32) * 1550 = 862K per tutte le istanze, come si vede che non è la preoccupazione quando si dispone di gigabyte ciascuno in dicts e carri allegorici.

+0

Se inserisco un intervallo (1000) o un intervallo (1250) anziché 1500 nel codice sopra, ottengo una dimensione di 24712 byte. Questo sembra essere vero fino alla gamma (1365) a quel punto c'è un salto discreto nella dimensione. E 'vero quanto Python alloca la memoria? Se è così, perché è così? – Wilduck

+0

Ho pensato che un float Python fosse implementato usando un doppio C, che sarebbe generalmente a 64 bit (8 byte). E il doppio tipo prende 8 byte nel modulo 'struct'. Non posso discutere con il risultato del 'getsizeof' però ... –

+1

@Scott, ogni oggetto Python ha qualche overhead (contatore di riferimento, puntatore al tipo) oltre al suo" payload ", e tutte le allocazioni sono arrotondate per eccesso a più di 16 byte per giocare bene insieme al sistema malloc. Per mantenere i float in modo compatto, puoi usare un 'array.array' (ma è simile a una lista, non a dict-like). –