3

.NET スレッド モデルをよりよく理解しようとしています。.NET スレッドは少なくとも 1MB のメモリを消費する (スタック用に 1MB を確保するため) ということを何度も聞いたり読んだりしました (最近ではこのビデオを見たとき: AppFabric.tv - Threading with Jeff Richter )。さて、これを実証するためにいくつかのコードを書き込もうとしましたが、最終的には次のような結果になります

297 threads are using 42MB of memory
298 threads are using 43MB of memory
299 threads are using 40MB of memory
300 threads are using 40MB of memory

そのため、スレッドはそれぞれ 1MB のメモリを使用していないようです。前述のビデオの 5 分間で示されたプログラムを再現するために最善を尽くしましたが、同じ結果が得られないようで、その理由がわかりません。メモリ消費量が時々減少しているように見えるので、スレッドが終了するか、どこかでバックバーナーに置かれる必要があると思いますか? それとも、メモリを適切に測定していないのでしょうか。

上記の結果を得るために使用されるプログラムは次のようになります。

class Program
{
    static void Main(string[] args)
    {
        ManualResetEvent manualReset = new ManualResetEvent(false);
        int createdThreads = 0;
        try
        {
            while (true)
            {
                Thread t = new Thread(WaitOneEvent);
                t.Start(manualReset);
                createdThreads++;
                Console.WriteLine("{0} threads are using {1}MB of memory", createdThreads, System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64 / (1024 * 1024));
            }
        }
        catch (OutOfMemoryException)
        {
            Console.WriteLine("Out of memory at {0} threads", createdThreads);
            System.Diagnostics.Debugger.Break();
            manualReset.Set();
        }
    }

    private static void WaitOneEvent(object eventObject) {
        ((ManualResetEvent)eventObject).WaitOne();
    }
}

どんな洞察も大歓迎です。

4

2 に答える 2

2

使いたいかもしれませんVirtualMemorySize64()が、PrivateMemorySize64().

MSはここに書いています

新しいスレッドまたはファイバーはそれぞれ、予約されたメモリと最初にコミットされたメモリの両方で構成される独自のスタック スペースを受け取ります。予約済みメモリ サイズは、仮想メモリ内の合計スタック割り当てを表します。[...] 最初にコミットされたページは、参照されるまで物理メモリを使用しません。[...]

OP のサンプル コードのスレッドは、シグナルを待機する以外に何もしないため、それらの (スタック) メモリは物理メモリを使用しないため、 によって考慮されませんPrivateMemorySize64()

于 2012-10-27T15:33:55.660 に答える
1

スレッドスタックのメモリ消費量を正確に追跡するには、測定値が粗すぎます。別のプロセスと共有できない仮想メモリの量を測定します。.NETプロセスで共有可能な唯一のメモリは、コード、ネイティブWindows DLL、CLR、ジッター、およびngen.exeによって生成されたネイティブイメージ(通常は.NET Frameworkアセンブリのみ)です。

それ以外はすべてプライベートメモリです。Jittedコード、ローダーヒープ、およびガベージコレクションされたヒープが主要なチャンクです。ガベージコレクターは、可能な場合は仮想メモリの割り当てを縮小します。

SysInternalsのVMMapユーティリティを使用すると、仮想メモリの使用状況をより正確に把握できます。詳細に溺れますが、スレッドスタックは別のカテゴリとして表示されます。

于 2012-10-27T16:08:40.480 に答える