1

私は、メモリ消費量が時間とともに着実に増加するPythonコードを持っています。合法的にかなり大きくなる可能性のあるオブジェクトがいくつかありますが、私が観察しているメモリフットプリントがこれらのオブジェクトによるものなのか、それとも適切に廃棄されない一時的なものでメモリを散らかしているだけなのかを理解しようとしています。 ---手動メモリ管理の世界からの最近の変換であるため、Pythonランタイムが一時オブジェクトを処理する方法のいくつかの非常に基本的な側面を正確に理解していないと思います。

大まかにこの一般的な構造のコードを考えてみましょう(無関係な詳細は省略しています)。

def tweak_list(lst):
    new_lst = copy.deepcopy(lst)
    if numpy.random.rand() > 0.5:
        new_lst[0] += 1  # in real code, the operation is a little more sensible :-)
        return new_lst
    else:
        return lst


lst = [1, 2, 3]
cache = {}

# main loop
for step in xrange(some_large_number):

    lst = tweak_list(lst)    # <<-----(1)

    # do something with lst here, cut out for clarity

    cache[tuple(lst)] = 42   # <<-----(2)

    if step%chunk_size == 0:
        # dump the cache dict to a DB, free the memory (?)
        cache = {}           # <<-----(3)

質問:

  1. new_listで作成されたの寿命はtweak_listどれくらいですか?出口で破棄されますか、それともガベージコレクションされますか(その時点で?)。tweak_list何億もの小さなリストを生成するための繰り返しの呼び出しは、長い間残っていますか?
  2. キーとして使用するためlistにaをに変換するときに一時的な作成はありますか?tupledict
  3. dictを空に設定すると、メモリが解放されますか?
  4. それとも、私は完全に間違った視点から目前の問題に取り組んでいますか?
4

2 に答える 2

4
  1. new_lst返されない場合、関数が存在する場合はクリーンアップされます。参照カウントが 0 になり、ガベージ コレクションが可能になります。現在の cpython 実装では、すぐに発生します。

    返された場合new_lst、によって参照される値が置き換えられますlst。によって参照されるリストは、そのlst参照カウントが 1 減少することを確認しますが、最初に参照される値new_lstは、別の変数によって参照されています。

  2. tuple()キーは に格納されている値であるためdict、一時的なものではありません。そのタプル以外に余分なオブジェクトは作成されません。

  3. cache古いdict を新しいものに置き換えると、参照カウントが 1 つ減ります。辞書への唯一の参照である場合cache、それはガベージコレクションされます。これにより、含まれているすべてのタプル キーの参照カウントが 1 つ減少します。それらへの参照が他にない場合、それらはガベージコレクションされます。

  4. Python がメモリを解放しても、オペレーティング システムがすぐにメモリを解放するとは限らないことに注意してください。ほとんどのオペレーティング システムは、別の目的で必要になったときにのみメモリを再利用します。その代わりに、プログラムがそのメモリの一部またはすべてをすぐに再び必要とする可能性があると想定します。

于 2012-12-09T13:18:19.480 に答える
0

メモリ使用量をプロファイリングする方法として、Heapyを確認することをお勧めします。これにはPySizerも使用される場合があると思いますが、私はそれに慣れていません。ObjGraphは、見てみるのにも強力なツールです。

于 2012-12-09T13:10:36.103 に答える