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