2

Python インタープリターで次のコードを実行しようとすると、メモリ使用量を確認するために無限ループを実行しているため、明らかな MemoryError が返されます。

def a():
 i=2
 while True:
  yield i
  i*=i

print sum(a())

このコードを実行すると、Python のメモリ使用量が増えていることがわかります。しかし、MemoryError が発生すると、インタプリタで sum 関数が実行されなくなった場合でも、Python インタプリタ プロセスがまだ約 200 MB のメモリを保持していることがわかります。私の質問は次のとおりです。python の組み込み関数は、ガベージ コレクションに関しても非常に効率的であると想定されていませんか? ユーザーへのガベージ コレクションの責任を処理する代わりに、ビルトインは独自のクラッターを片付けませんか?

4

3 に答える 3

3

Python ビルトインにメモリ リークがある場合、それはバグです。

ただし、Python がまだメモリを保持しているからといって、メモリ リークがあるとは限りません。Python にはあらゆる種類の楽しい割り当てトリックが進行しているため、将来の使用のためにメモリを保持している可能性があります。そのため、Python がメモリを適切に処理しているかどうかをタスク マネージャーで確認するだけでは不十分です。

実際のメモリ リークをチェックする 1 つの方法は、コードを繰り返し実行することです。実際のメモリ リークの場合は、実行するたびにメモリが失われるはずです。ファントム メモリ リークの場合、メモリは実際に 2 回目に再利用されるため、メモリが失われることはありません。

Linuxボックスでコードを実行しましたが、そのループをしばらく実行した後、以前よりもはるかに多くのメモリを使用していることがわかりましたが、再度実行しても追加のメモリは使用されませんでした。実際、メモリの一部が「失われました」最初の実行で回復したようです。

于 2012-08-30T18:22:31.857 に答える
2

Free Listsの GC に関する Python ドキュメント:

特定の実装、特に int と float が原因で、一部のフリー リストのすべてのアイテムが解放されるわけではありません。

したがって、ジェネレーターを介して無数の無限の整数を割り当てると、すべてのメモリが (メモリ エラーを受け取るまで) 消費されますが、上記の定義に従ってすべてのアイテムが解放されるわけではありません。

しかし、その記憶は永久に失われていますか?いいえ。環境は、コードで再利用できるように保持します。ガベージ コレクションは「効率的」であるからといって、オブジェクトがスコープを離れた瞬間に回収されるわけではありません。また、「使用したばかりのメモリを保持しましょう。このばかげたコードが再び使用する可能性がある」という意味もあります。

または、Effbotが教えてくれるように:

特定のアロケーターに返されたメモリは、システムに返されなくても、そのアロケーターによって再利用されます。

GC コレクションを強制することはでき ますが、その理由がわからず、強制する非常に正当な理由がない限り、実際にはパフォーマンスが低下する可能性があります。

gc.collect([generation])
With no arguments, run a full collection. The optional argument generation may be an integer specifying which generation to collect (from 0 to 2). A ValueError is raised if the generation number is invalid. The number of unreachable objects found is returned.

Changed in version 2.5: The optional generation argument was added.

Changed in version 2.6: The free lists maintained for a number of built-in types are cleared whenever a full collection or collection of the highest generation (2) is run. Not all items in some free lists may be freed due to the particular implementation, in particular int and float.
于 2012-08-31T12:09:05.620 に答える
1

sumこれは、ジェネレータ、ガベージコレクタの実装とは何の関係もありません。

表示されているメモリ使用量の増加は、の値を保持するために必要なものですi。Pythonは任意の大きさの整数をサポートし、反復ごとにidoubleを格納するために必要なビット数をサポートします。ジェネレーター関数を次のように変更すると、次のようになります。

def a():
    i=2
    while True:
        yield i
        i += 1

メモリフットプリントが安定していることがわかります。

于 2012-08-30T18:47:24.147 に答える