2013-06-05 5 views
5

Pythonの単純なリンクリストとそのメモリ消費に関する問題があります。Pythonでのメモリ割り当てが悪いLinkedList

これはコードです:

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" 

私の問題はこれです:このスクリプトを実行すると、私のRAMの1.7ギガバイトを消費します。

出力がある:レコードの

10百万人:

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

はそれでは、いくつかの簡単な数学をやらせます。

各レコードは持っ12バイト(ELEM)+ 8バイト(次のものへのポインタ)= 20バイト

20バイト×1000万= 200.000.000バイト= 190.7メガバイト

たとえI range()関数によって割り当てられたリスト(約30 MB)を考慮する必要があります。その膨大なメモリ消費量をどのように管理できますか?私はこのコードでいくつかばかげたミスをしたことがありますか?私は答えが恥ずかしいと感じるようになり、それを尋ねるのは残念ですが、知っている限り、私は何が起こっているのだろうかと思っています!

ご協力いただきありがとうございます。

+2

大きなギャップを埋めるわけではありませんが、 '' 'Record'''の' '' size''メソッドを変更して '' 'sys.sizeof(self)' ''を表示させるべきです2つの構成要素のうちの1つである。クラス構造にオーバーヘッドがあるため、32バイトで、20ではありません。 –

+1

断片化は何かを追加します。私は 'recpool = [None] * 10000000;のようなものを試してみます。 ... rec = recpool [j]; j + = 1'となり、何が起こるか見る。 – Elazar

+1

また、 'gc.disable()'を試してください。 – Elazar

答えて

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

何か不足していますか?

また、私のシステム上:

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

私のマシンでは56です – Elazar

+0

それについて今考えてみましょう:56または72バイト、それでも1.7GBまで増やすべきではありません。 56バイトで、その数学は〜600MBにあります。私はそれについて考え続けます:) – 2rs2ts

+0

56 + 28 = 84。切り上げ - 88. 88 * 10000000〜= 0.88GB。断片化とGCオーバーヘッドを追加すると、近いものがあります。 – Elazar

0

変化したプリントアウトを次のように

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) 

出力:

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

だから、私のリンクリストの各ノードは72ですバイト×10Mは720MB、.72GB

私はプログラムを実行し、topを使って、メモリオーバーヘッドが3.6Gであることを見た。 私のelemのサイズはあなたのものの2倍であり、私はあなたが使っているメモリの合計(1.7Gと比較して3.6G)の2倍に気づいています。

これは、ガベージコレクションなどの追加のPythonメモリオーバーヘッドが原因である必要があります。