eryksunが質問#1に回答し、質問#3(元の#4)に回答しましたが、今度は質問#2に回答しましょう。
特に50.5mbをリリースするのはなぜですか?リリースされる量は何に基づいていますか?
それが基づいているのは、結局のところ、Python内部での一連の偶然の一致であり、malloc
これは予測が非常に困難です。
まず、メモリの測定方法によっては、実際にメモリにマッピングされているページのみを測定している場合があります。その場合、ページャーによってページがスワップアウトされると、メモリは解放されていなくても「解放された」と表示されます。
または、割り当てられているが変更されていないページ(Linuxのように楽観的に過剰割り当てされているシステム)、割り当てられているがタグ付けされているページMADV_FREE
などをカウントする場合とカウントしない場合がある使用中のページを測定している場合があります。
割り当てられたページを実際に測定していて(実際にはそれほど有用なことではありませんが、それはあなたが求めていることのようです)、ページが実際に割り当て解除された場合、これが発生する可能性のある2つの状況は次のとおりです。brk
データセグメントを縮小するために使用または同等のもの(最近では非常にまれです)、またはmunmap
マッピングされたセグメントを解放するために使用または類似しています。(また、理論的には、マッピングされたセグメントの一部を解放する方法があるなど、後者のマイナーバリアントもあります。たとえば、すぐにマップ解除MAP_FIXED
したMADV_FREE
セグメントのためにそれを盗みます。)
しかし、ほとんどのプログラムは、メモリページから直接物事を割り当てません。それらは- malloc
スタイルのアロケーターを使用します。を呼び出すfree
と、アロケータはfree
、マッピング(またはデータセグメントの最後のNページ)の最後のライブオブジェクトをたまたま使用している場合にのみ、OSにページを解放できます。アプリケーションがこれを合理的に予測したり、事前に発生したことを検出したりすることはできません。
CPythonのは、これはさらに複雑-それはの上にカスタムメモリアロケータの上にカスタム2レベルのオブジェクトアロケータを持っていますmalloc
。(さらに詳しい説明については、ソースのコメントを参照してください。)さらに、C APIレベルでさえ、Pythonははるかに少なく、トップレベルのオブジェクトが割り当て解除されるタイミングを直接制御することすらできません。
では、オブジェクトを解放するときに、それがOSにメモリを解放するかどうかをどのようにして知るのでしょうか。まあ、最初に、最後の参照(知らなかった内部参照を含む)を解放したことを知って、GCが割り当てを解除できるようにする必要があります。(他の実装とは異なり、少なくともCPythonは許可されたらすぐにオブジェクトの割り当てを解除します。)これは通常、次のレベルで少なくとも2つのものの割り当てを解除します(たとえば、文字列の場合、PyString
オブジェクトと文字列バッファーを解放します) )。
あなたがいる場合行う、これはオブジェクトストレージのブロックを解放する次のレベルのダウンを引き起こすかどうかを知るために、オブジェクトを解放し、あなたはそれを実現していますかだけでなく、オブジェクトアロケータの内部状態を知っている必要があります。(ブロックの最後の割り当てを解除しない限り、明らかに発生することはありません。それでも発生しない場合があります。)
あなたがいる場合行う、これが原因かどうかを知るために、オブジェクトストレージのブロックの割り当てを解除するfree
コールを、あなたはそれが実装されますかだけでなく、PyMemアロケータの内部状態を知っている必要があります。(繰り返しますが、malloc
ed領域内の使用中の最後のブロックの割り当てを解除する必要がありますが、それでも発生しない場合があります。)
edリージョンを実行 free
する場合malloc
、これがmunmap
や同等の(またはbrk
)を引き起こすかどうかを知るには、の内部状態と、そのmalloc
実装方法を知る必要があります。そして、これは他とは異なり、プラットフォーム固有のものです。(そして繰り返しますが、通常malloc
、mmap
セグメント内で使用中の最後の割り当てを解除する必要がありますが、それでも発生しない場合があります。)
それで、なぜそれがちょうど50.5mbをリリースしたのかを理解したいのであれば、それをボトムアップでトレースする必要があります。malloc
これらの1つ以上のfree
呼び出しを行ったときに50.5mb相当のページのマップを解除したのはなぜですか(おそらく50.5mbより少し多い)。プラットフォームのを読みmalloc
、さまざまなテーブルやリストを調べて現在の状態を確認する必要があります。(一部のプラットフォームでは、システムレベルの情報を利用することもあります。オフラインで検査するシステムのスナップショットを作成せずにキャプチャすることはほとんど不可能ですが、幸い、これは通常問題ではありません。)そして、その上の3つのレベルで同じことを行います。
したがって、質問に対する唯一の有用な答えは「理由」です。
リソースが限定された(組み込みなど)開発を行わない限り、これらの詳細を気にする必要はありません。
あなたがいる場合とされているリソースが制限された開発を行って、これらの詳細を知ることは無用です。これらのすべてのレベル、特にmmap
アプリケーションレベルで必要なメモリ(おそらく、間に単純な、よく理解されているアプリケーション固有のゾーンアロケータが1つある場合)をエンドランする必要があります。