2011-02-09 8 views
3

Python 2.6で書かれたプログラムは、多くの短命のインスタンスを作成します(これは古典的なプロデューサ/コンシューマの問題です)。私は、これらのインスタンスが作成され、決して元に戻ってこないと、topとpmapによって報告されるメモリ使用量が増加するように見えることに気付きました。私が使用していたいくつかのPythonモジュールがメモリをリークしている可能性があることを懸念していましたので、私のコードで問題を慎重に切り離しました。私は可能な限り短い例でそれを再現しました。あなたは「のpython2.6 -i memoryleak.py」のようなものでこれを実行した場合、それは停止します、あなたはメモリ使用量をチェックするには、pmap -x PIDを使用することができますPython 2.6 GCがオブジェクトをクリーンアップするのに表示されますが、メモリは解放されません。

class LeaksMemory(list): 
    timesDelCalled = 0 

    def __del__(self): 
     LeaksMemory.timesDelCalled +=1 


def leakSomeMemory(): 
    l = [] 
    for i in range(0,500000): 
     ml = LeaksMemory() 
     ml.append(float(i)) 
     ml.append(float(i*2)) 
     ml.append(float(i*3)) 
     l.append(ml) 

import gc 
import os 


leakSomeMemory() 

print("__del__ was called " + str(LeaksMemory.timesDelCalled) + " times") 
print(str(gc.collect()) +" objects collected") 
print("__del__ was called " + str(LeaksMemory.timesDelCalled) + " times") 
print(str(os.getpid()) + " : check memory usage with pmap or top") 

:私はこれを思い付きました。 delメソッドを追加して、GCが発生していることを確認できました。私の実際のプログラムにはありませんし、機能的な違いはありません。 leakSomeMemory()を呼び出すたびに、このプログラムが消費するメモリ量が増えます。私はいくつかの単純な誤りを犯していることを恐れ、その参照は偶然に保管されているが、それを特定することはできません。

+0

をあなたはしばらく待っていれば、メモリの消費量が戻ってダウンして行くのでしょうか?私の理解では、Pythonはプールから割り当てを行うため、プールを拡張する必要がある場合、メモリを解放した直後にプールを縮小することはありません。 –

答えて

8

Pythonはオブジェクトをリリースしますが、メモリをすぐにオペレーティングシステムに戻すことはありません。代わりに、同じインタプリタ内で将来の割り当てに同じセグメントを再利用します。ここで

は、問題についてのブログ記事です:http://effbot.org/pyfaq/why-doesnt-python-release-the-memory-when-i-delete-a-large-object.htm

UPDATE:私は、Python 2.6.4でこれを自分自身をテストし、メモリ使用量の持続的な増加に気付きませんでした。 leakSomeMemory()の呼び出しによって、Pythonプロセスのメモリ占有量が増加し、一部のものが再び減少しました。したがって、すべてはアロケータがメモリをどのように再利用しているかに依存します。

4

Alex Martelliによると:

は「 にだけは本当に信頼できる方法は、それが終了したときのメモリの大きいが一時的に使用 は、 にシステムをすべてのリソースを返すないことを確認して使用し を持つことですサブプロセスで発生します。 はメモリを必要とし、 は終了します。だから、

それはプロセスが終了したときに、リソースのリターンを確保するために、別のプロセスで短命な機能を実行するためにmultiprocessingモジュールを使用するように理にかなってのように、あなたの状況ではそれが聞こえます。マルチプロセッシングを使用して物事を設定する方法についてのより多くのアイデアについては

import multiprocessing as mp 

def NOT_leakSomeMemory(): 
    # do stuff 
    return result 


if __name__=='__main__': 
    pool = mp.Pool() 
    results=pool.map(NOT_leakSomeMemory, range(500000)) 

Doug Hellman's tutorial参照:

関連する問題