2011-06-30 11 views
5
import json 
import time 
from itertools import count 

def keygen(size): 
    for i in count(1): 
     s = str(i) 
     yield '0' * (size - len(s)) + str(s) 

def jsontest(num): 
    keys = keygen(20) 
    kvjson = json.dumps(dict((keys.next(), '0' * 200) for i in range(num))) 
    kvpairs = json.loads(kvjson) 
    del kvpairs # Not required. Just to check if it makes any difference        
    print 'load completed' 

jsontest(500000) 

while 1: 
    time.sleep(1) 

Linuxのトップ pythonのプロセスは 'jsontest' 関数の完了後にRAMの〜450MBを保持していることを示しています。 'json.loads'への呼び出しが省略されている場合、この問題は発生しません。 A gc.collectこの関数実行後はメモリを解放しません。PythonのJSONメモリ肥大化

gc.collectの明示的な呼び出しがメモリを解放しているので、メモリがキャッシュまたはPythonの内部メモリアロケータに保持されていないように見えます。

ガベージコレクション(700,10,10)のしきい値に達していないため、これは起こっていますか?

jsontestの後にコードを入力して、しきい値をシミュレートしました。しかし、それは役に立たなかった。

答えて

2

あなたのプログラムの先頭

import gc 
gc.set_debug(gc.DEBUG_STATS) 

でこれを入れて、コレクションがありますたびに出力を印刷しますよ。プログラムが終了するまで、jsontestが完了した後、サンプルコードにコレクションがないことがわかります。

現在のカウントを見に

print gc.get_count() 

を置くことができます。最初の数は、世代0の最後のコレクション以降の割り当て解除を超えた割り当てです。 2番目(3番目)は世代1(2番目)の最後の収集以降に世代0(1)が収集された回数です。 jsontestが完了した直後にこれらを印刷すると、数が(548, 6, 0)か何か類似していることがわかります(これはPythonのバージョンによって異なります)。したがって、しきい値に達しておらず、収集が行われていませんでした。

これは、しきい値ベースのガベージコレクションスケジューリングの一般的な動作です。オペレーティング・システムに空きメモリーを適時に戻す必要がある場合は、しきい値ベースのスケジューリングと時間ベースのスケジューリングを組み合わせる必要があります(つまり、前回の収集から一定の時間が経過した後に別の収集を要求する必要がありますたとえ閾値に達していなくても)。

+0

jsontestを複数回呼び出しても、メモリは〜450MBのままです。これは最後のjsontestコールで使用されたメモリですか?このコードは、jsonメッセージを処理するwebappの一部です。 webappを1時間実行しても、メモリは解放されていないようです。 gc.collect以外の回避策がありますか? – Anoop

+1

'jsontest'を呼び出すたびに' gc.get_count() 'を表示してみてください。また、 'gc.collect'を呼び出すのに何が問題になりますか? –

関連する問題