親愛なるアルターさん、あなたの推測がどれほど的外れで、以前に何度も人々があなたに言ったことを聞いていないことに、私は目がくらみました。
いくつかのことを整理しましょう。メモリ管理 101. よくお読みください。
Delphi でメモリを割り当てる場合、2 つのメモリ マネージャが関与します。
システムメモリマネージャー
1 つ目は、システム メモリ マネージャーです。これは Windows に組み込まれており、4kb サイズのページでメモリを提供します。
ただし、常に RAM (または物理メモリ) にメモリが提供されるとは限りません。データをハード ドライブに保存し、アクセスする必要があるたびに読み返すことができます。これは非常に遅いです。
つまり、512Mb の物理メモリがあるとします。2 つのプログラムを実行し、それぞれが 1Gb のメモリを要求します。OSは何をしますか?
両方の要求を許可します。どちらのアプリもそれぞれ 1Gb のメモリを取得します。どちらも、すべてのメモリが「メモリ内」にあると考えています。しかし実際には、RAM に保持できるのは 512Mb だけです。残りはページ ファイルに保存されますが、アプリはそれを認識しません。動作が遅いだけです。
ワーキング セットのサイズ
さて、あなたが測定している「ワーキングセットサイズ」とは何ですか?
RAMに保持されるのは、割り当てられたメモリの一部です。
1Gb のメモリを割り当てるアプリケーションがあり、RAM が 512Mb しかない場合、ワーキング セットのサイズは 512Mb になります。1Gbのメモリを「使用」しますが!
メモリを必要とする別のアプリケーションを実行すると、OS はめったに使用されない「メモリ」のブロックをハード ドライブに移動して、RAM を自動的に解放します。
仮想メモリの割り当ては変わりませんが、ハード ドライブのページ数が増え、RAM のページ数が減ります。ワーキング セットのサイズが減少します。
このことから、ワーキング セットのサイズを最小化しようとするのは無意味であることを、この時点で理解しているはずです。あなたは何も達成していません。何らかの意味でメモリを解放していません。データをハードドライブにオフロードしているだけです。
ただし、システムは必要なときに自動的にそれを行います。また、必要になるまで RAM にスペースを確保しても意味がありません。アプリケーションの速度が低下しているだけです。それだけです。
TLDR : 「ワーキング セット サイズ」は「アプリケーションが使用するメモリ量」ではありません。それは「今どれだけ準備ができているか」です。それを最小限に抑えようとしないでください。事態を悪化させるだけです。
Delphi メモリ マネージャ
OS は 4Kb のページ単位で仮想メモリを提供します。しかし、多くの場合、はるかに小さなチャンクでそれが必要になります。たとえば、整数の場合は 4 バイト、構造体の場合は 32 バイトです。ソリューション?
FastMM や BorlandMM などのアプリケーション メモリ マネージャー。
その仕事は、オペレーティング システムからメモリをページに割り当て、必要なときにそれらのページの小さなチャンクを提供することです。
つまり、14 バイトのメモリを要求すると、次のようになります。
- FastMM に 14 バイトのメモリを要求します。
- FastMM は OS に 1 ページのメモリ (4096 バイト) を要求します。
- OS は 1 ページのメモリを許可し、RAM でバックアップします (実際の RAM に保存されます)。
- FastMM はそのページを保存し、14 バイトを切り取って提供します。
さらに 14 バイトを要求すると、FastMM は同じページからさらに 14 バイトをカットします。
メモリを解放するとどうなりますか?同じことを逆に:
- 14 バイトを FastMM に解放します。何も起こりません。
- さらに 14 バイトを解放します。FastMM は、割り当てた 4096 バイトのページが完全に使用されていないことを確認します。
- したがって、ページを解放してシステムに戻します。
FastMMは14 バイトだけをシステムに解放できないことに注意してください。ページ単位でメモリを解放する必要があります。ページ全体が解放されるまで、FastMM は何もできません。誰もできません。
では、すべてをリリースしたにもかかわらず、ワーキング セットのサイズがこれほど大きいのはなぜでしょうか。
まず、ワーキング セットのサイズは測定すべきサイズではありません。仮想メモリの消費量です。ただし、ワーキング セットのサイズが大きいと、仮想メモリの消費量も多くなります。
どうしたの?この時点でわかるはずです。
1kb を割り当て、次に 3kb のメモリを割り当てるとします。どのくらいの仮想メモリを割り当てましたか? 4KB、1ページ。
ここで 3Kb を解放します。現在、どのくらいの仮想メモリを使用していますか? 1Kb? いいえ、まだ 1 ページです。システムから 1 ページ未満を割り当てることはできません。まだ 4096 バイトの仮想メモリを使用しています。
それを1000回行ったとします。1kb、3kb、1kb、3kb、1kb、3kbなど。そのように 1000 * 4kb = 4 mb を割り当ててから、3kb の部分をすべて解放します。現在、どのくらいの仮想メモリを使用していますか?
それでも4MB。最初に 1000 ページを割り当てたからです。すべてのページのうち、1kb と 3kb のチャンクを取得しました。3kb のチャンクを解放しても、1kb のチャンクはメモリに割り当てたすべてのページを保持し続けます。また、各ページには 4kb の仮想メモリが必要です。
メモリ マネージャーは、魔法のように 1kb のチャンクすべてをまとめて「移動」することはできません。仮想アドレスはコードのどこかから参照できるため、これは不可能です。これは FastMM の特徴ではありません。
しかし、BorlandMM を使用すると、すべてがうまく機能するのはなぜでしょうか?
一致。BorlandMM が FastMM とは少し異なる方法でメモリを提供するのは、たまたまのことかもしれません。次に、アプリで何かを変更すると、BorlandMM は FastMM と同じように動作します。メモリ マネージャが、メモリの断片化と呼ばれるこの影響を完全に防ぐことは不可能です。
それで、私は何をしますか?
短い答えは、これが気になるまではあまりありません。
おわかりのように、最新のオペレーティング システムでは、実際に誰かの RAM を消費することはありません。上記のとおり、OS は、他のアプリケーションのために RAM が必要になると、自動的にページをスワップアウトします。これは心配する必要はありません。
そして、「過剰な」記憶は失われません。ページは割り当てられていますが、それぞれの 3kb は「空き」としてマークされています。次にアプリがメモリを必要とするとき、メモリ マネージャーはその領域を使用します。
しかし、本当にそれを助けたい場合は、割り当てを再編成して、保持する予定の割り当てが最初に行われ、すぐにリリースする割り当てがすべてその後に割り当てられるようにする必要があります。
このように: 1kb、1kb、1kb、...、3kb、3kb、3kb...
ここで 3kb のチャンクをすべて解放すると、仮想メモリの消費量が大幅に減少します。
これは常に可能であるとは限りません。それが不可能な場合は、何もしないでください。ほぼそのままで大丈夫です。
そして追伸
そもそも 500 フォームを割り当てるべきではありません。これは明らかに進むべき道ではありません。これを修正すると、メモリの割り当てと解放について考える必要さえなくなります。
率直に言って、同じトピックに関する4つの投稿は少し多すぎるため、これで問題が解決することを願っています.