2013-06-05 9 views
5

Ich habe ein Problem in Bezug auf eine Python einfache verknüpfte Liste und deren Speicherverbrauch.Schlechte Speicherzuweisung in Python LinkedList

Dies ist der Code:

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" 

Mein Problem ist folgendes: dieses Skript ausgeführt wird verbraucht 1,7 GB meiner RAM.

Ausgang ist:

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

so, lassen Sie uns einige schnelle Mathematik tun:

10 Millionen Datensatz.

Jeder Datensatz bekam 12 Byte (Elem) + 8 Bytes (Zeiger auf nächste) = 20 Bytes

20 Bytes * 10 Millionen = 200.000.000 Bytes = 190,7 MB

Auch wenn ich muss die von der range() -Funktion zugewiesene Liste (ca. 30 MB) berücksichtigen, wie kann ich diese riesige Lücke des Speicherverbrauchs bewältigen? Habe ich in diesem Code einen dummen Fehler gemacht? Ich hoffe, die Antwort wird mich beschämen und entschuldigen, dass ich sie gefragt habe, aber ich weiß nur, was passiert ist!

Vielen Dank im Voraus für Ihre Hilfe.

+2

Nicht, dass es die große Lücke ausmacht, aber Sie sollten die '' '' '' '' 'Methode von' 'Record''' ändern und es' '' sys.sizeof (self) '' 'stattdessen drucken lassen der zwei Komponentenelemente. Es ist 32 Bytes, nicht 20, weil in der Klassenstruktur Overhead ist. –

+1

Fragmentierung wird etwas hinzufügen, denke ich. Ich würde versuchen, etwas wie 'repool = [None] * 10000000; ... rec = recpool [j]; j + = 1' und sehen was passiert. Versuchen Sie auch – Elazar

+1

'gc.disable()'. – Elazar

Antwort

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

Oder fehlt mir etwas?

Auch auf meinem System:

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

ist es 56 auf meiner Maschine – Elazar

+0

Denken Sie darüber jetzt nach : 56 oder 72 Bytes, sollte es immer noch nicht zu 1,7 GB addieren. Bei 56 Bytes liegt diese Mathematik bei ~ 600 MB. Ich werde darüber nachdenken :) – 2rs2ts

+0

56 + 28 = 84. runden - 88. 88 * 10000000 ~ = 0.88GB. Fügen Sie Fragmentierung und GC-Overhead hinzu und Sie haben etwas in der Nähe. – Elazar

0

Altered Ausdruck wie folgt:

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) 

Ausgang:

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

Also, jeder meiner verknüpften Liste Knoten 72 Bytes x 10M sollten 720 MB sein, .72GB

Ich lief das Programm, und mit Top, sah, dass der Speicheraufwand 3.6G war. Meine elem Größe ist doppelt Ihre, und ich merke doppelt so viel Speicher wie Sie verbraucht sind (3.6G, im Vergleich zu 1.7G).

Dies muss auf zusätzlichen Python-Speicher-Overhead zurückzuführen sein, z. B. Garbage Collection.