eryksunは、質問#1に答えた、と私は質問#3(元#4)答えましたが、今の質問#2答えてみましょう:なぜそれは特に50.5メガバイトを解放ん
を - それに基づいてリリースされる金額はいくらですか?
最終的には、Pythonとmalloc
内の一連の偶然の一致は、予測が非常に困難です。
まず、あなたがメモリを測定している方法に応じて、あなただけの、実際にメモリにマップされたページを測定することができます。その場合、ページャがページをスワップアウトすると、メモリは解放されていなくても「解放された」と表示されます。
または、割り当てられているが決して触られていないページ(Linuxのように楽観的に過剰に割り当てられたシステム)、割り当てられたがタグが割り当てられたページはMADV_FREE
などの使用中のページを測定している可能性があります。
割り当てられたページを実際に測定している場合(実際には非常に便利なことではありませんが、質問しているようです)、ページは実際に割り当てが解除されています。起こった:brk
または同等のデータセグメントを(最近はまれに)縮小するために使用したか、munmap
または類似のものを使用してマップされたセグメントを解放したかのいずれかです。 (マップされたセグメントの一部を解放する方法がある(つまり、すぐにマップ解除するMADV_FREE
セグメントの場合はMAP_FIXED
で盗むなどの方法もあります)。
ほとんどのプログラムでは、メモリページから直接物を割り当てる。彼らはmalloc
スタイルのアロケータを使用します。 free
を呼び出すと、マッピング内の最後のライブオブジェクト(またはデータセグメントの最後のNページ)がfree
になった場合にのみ、アロケータはOSにページを解放できます。アプリケーションがこれを合理的に予測する方法や、事前に発生したことを検出する方法はありません。
CPythonはこれをさらに複雑にしています。カスタムメモリアロケータの上にカスタム2レベルオブジェクトアロケータがあり、その上にmalloc
があります。 (詳細については、the source commentsを参照してください)。さらに、C APIレベルでさえ、Pythonがはるかに少なくても、最上位レベルのオブジェクトの割り当てを解除するタイミングを直接制御することさえできません。
オブジェクトをリリースすると、OSがメモリを解放するかどうかをどのように知ることができますか?最初に、最後のリファレンス(あなたが知らなかった内部参照を含む)をリリースし、GCがそれを割り当て解除できるようにする必要があります。 (他の実装と違って、少なくともCPythonはオブジェクトが割り当てられたらすぐにオブジェクトの割り当てを解除します)。これは通常、次のレベルで少なくとも2つのオブジェクトを解放します(例えば、文字列の場合はPyString
オブジェクトを解放し、バッファ)。あなたはこれはオブジェクトストレージのブロックを解放する次のレベルをダウン引き起こすかどうかを知るために、オブジェクトを解放しません場合
、あなたはそれが実装されていますかだけでなく、オブジェクトアロケータの内部状態を知っている必要があります。 (あなたがブロック内の最後の割り当てを解除していない限り、それは明らかに起こることができず、その後も、それが起こらないことがあります。)
をあなたはこれが原因かどうかを知るために、オブジェクトストレージの割り当て解除ブロックを行う場合free
コールでは、PyMemアロケータの内部状態とその実装方法を知る必要があります。 (ここでも、あなたはmalloc
編領域内の最後の使用中のブロックの割り当てを解除する必要があり、その後も、起こらないことがあります。)
をあなたはfree
malloc
編地域を行う場合は、これが原因かどうかを知るためにmunmap
または同等のもの(またはbrk
)の場合は、malloc
の内部状態とその実装方法を知る必要があります。これは、他のプラットフォームとは異なり、プラットフォーム固有のものです。 (また、一般的には最後に使用中のmalloc
をmmap
セグメント内に割り当て解除する必要がありますが、それでも発生しない可能性があります)。
なぜ、50.5MBを正確にリリースしたのか、あなたはそれを底から上まで追跡しなければならないでしょう。なぜmalloc
は1つ以上のfree
コールを実行したときに50.5MBのページをアンマップしたのでしょうか(おそらく50.5MBを少し上回ります)?あなたのプラットフォームのmalloc
を読んでから、さまざまなテーブルとリストを歩いて現在の状態を確認する必要があります。 (一部のプラットフォームでは、システムレベルの情報を利用することさえありますが、システムのスナップショットをオフラインで調べなければキャプチャすることはほとんど不可能ですが、幸運なことにこれは通常問題ではありません)。それ以上の3つのレベルで同じことをしてください。
この質問に対する唯一の有益な回答は、「理由」です。
リソースが限られている(埋め込み済みの)開発をしていない限り、これらの詳細を気にする必要はありません。
がリソース制限開発を行っているである場合、これらの詳細を知ることは役に立たない。すべてのレベル、特にアプリケーションレベルで必要なメモリをmmap
(おそらく単純でよく知られているアプリケーション固有のゾーンアロケータを1つ使用して)必要なメモリをエンドエンドで実行する必要があります。
この動作がPython固有のものではないことに注意してください。一般に、プロセスがヒープ割り当てメモリを解放すると、プロセスが終了するまでメモリはOSに解放されません。 – NPE
あなたの質問は複数のことを尋ねます - そのうちのいくつかはダブですが、その中には不適切なものがありますが、そのうちのいくつかは良い質問かもしれません。 Pythonがメモリを解放しないかどうか、それができるかどうか、根底にあるメカニズム、それがなぜそのように設計されたのか、回避策があるのか、それとも完全に他のものがあるのかを尋ねていますか? – abarnert
@abarnert私は類似したサブクラスを組み合わせました。あなたの質問に答えるには:私は、PythonがOSにいくつかのメモリをリリースするが、なぜそれがすべてではないのか、それがなぜあるのかという理由を知っている。それができない状況がある場合、なぜですか?どのような回避策もあります。 – Jared