2013-06-05 19 views
5

Ho qualche problema riguardante una semplice lista collegata a Python e il suo consumo di memoria.Allocazione di memoria errata in Python LinkedList

Questo è il codice:

import sys 

class Record: 
    def __init__(self,elem): 
     self.elem=elem 
     self.next=None 

    def size(self): 
     print 'elem.size = ', sys.getsizeof(self.elem) 
     print 'next.size = ', sys.getsizeof(self.next) 


class LinkedList: 
    def __init__(self): 
     self.first=None 
     self.last=None 

    def addAsLast(self,elem): 
     rec=Record(elem) 
     if self.first==None: 
      self.first=self.last=rec 
     else: 
      self.last.next=rec 
      self.last=rec 

if __name__=="__main__": 
    l=LinkedList() 
    r = Record(1) 
    r.size() 

    maxx = 10000000 
    r = range(1, maxx) 
    print 'size of r: ', sys.getsizeof(r) 
    print 'size of r[n-1]: ', sys.getsizeof(r[maxx-2]) 

    for i in r: 
     if(i% (maxx/10) == 0): print '.' 
     l.addAsLast(i) 
    print "The End" 

mio problema è questo: l'esecuzione di questo script consuma 1,7 GB di RAM mia.

uscita è:

elem.size = 12 
next.size = 8 
size of r: 40000028 
size of r[n-1]: 12 

così, cerchiamo di fare qualche rapido calcolo:

10 milioni di record.

ogni record ottenuto 12 byte (elem) + 8 byte (puntatore successivo) = 20 byte

20 byte * 10 milioni = 200.000.000 byte = 190.7 MB

Anche se io deve considerare l'elenco assegnato dalla funzione range() (circa 30 MB) come posso gestire quell'enorme perdita di memoria? Ho fatto qualche stupido errore in questo codice? Spero che la risposta mi faccia vergognare e dispiacere di averlo chiesto ma, fino a sapere, mi sto solo chiedendo cosa sta succedendo!

Grazie in anticipo per il vostro aiuto.

+2

Non che crei il grande spazio, ma dovresti modificare il metodo '' 'size''' di' '' Record''' e farlo stampare '' 'sys.sizeof (self)' '' dei due elementi componenti. È 32 byte, non 20 perché c'è un sovraccarico nella struttura della classe. La frammentazione –

+1

aggiungerà qualcosa, immagino. Vorrei provare qualcosa come 'recpool = [Nessuno] * 10000000; ... rec = recpool [j]; j + = 1' e vedi cosa succede. – Elazar

+1

, prova anche 'gc.disable()'. – Elazar

risposta

0
>>> class Record: 
...  def __init__(self, elem): 
...    self.elem = elem 
...    self.next = None 
... 
>>> r = Record(1) 
>>> sys.getsizeof(r) 
72 

O mi manca qualcosa?

Inoltre, sul mio sistema:

>>> sys.getsizeof(1) 
24 
>>> sys.getsizeof(None) 
16 
+0

è 56 sulla mia macchina – Elazar

+0

Pensandoci ora : 56 o 72 byte, non dovrebbe comunque aggiungere fino a 1,7 GB. A 56 byte, quella matematica ti ha ~ 600 MB. Continuerò a pensarci :) – 2rs2ts

+0

56 + 28 = 84. - 88. 88 * 10000000 ~ = 0.88 GB. aggiungi frammentazione e overhead GC e hai qualcosa vicino. – Elazar

0

Altered stampa come segue:

class Record: 
    def __init__(self,elem): 
     self.elem=elem 
     self.next=None 

    def size(self): 
     print 'Record size = ', sys.getsizeof(self) 
     print 'elem.size = ', sys.getsizeof(self.elem) 
     print 'next.size = ', sys.getsizeof(self.next) 

uscita:

Record size = 72 
elem.size = 24 
next.size = 16 

Così, ognuno dei miei nodi lista collegata è 72 byte x 10 M dovrebbe essere 720 MB, .72 GB

Ho eseguito il programma e, utilizzando la parte superiore, ho visto che l'overhead della memoria era 3.6G. La mia dimensione elem è doppia, e sto notando il doppio della memoria totale consumata come sei (3.6G, rispetto a 1.7G).

Questo deve essere dovuto al sovraccarico della memoria extra di Python, come la garbage collection.

Problemi correlati