为什么我的线程看起来占用的内存不到1MB?

时间:2012-10-27 14:31:13

标签: c# multithreading memory .net-4.5

我试图更好地掌握.NET线程模型。我多次听过和读过(最近观看这个视频的时候:AppFabric.tv - Threading with Jeff Richter).NET线程占用了至少1MB的内存(因为他们为它们的堆栈预留了1MB)。 现在,我尝试编写一些代码来演示这一点,但我最终得到了像

这样的结果
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();
    }
}

非常感谢任何见解。

2 个答案:

答案 0 :(得分:2)

您可能希望VirtualMemorySize64()使用PrivateMemorySize64()

MS writes here

  

每个新线程或光纤都有自己的堆栈空间   保留和最初提交的内存。保留的内存大小   表示虚拟内存中的总堆栈分配。 [...]最初   提交的页面直到它们才使用物理内存   引用; [...]

由于OP示例代码中的线程除了等待发信号之外什么都不做,因此它们(堆栈)内存不使用物理内存,因此PrivateMemorySize64()不会考虑它。

答案 1 :(得分:1)

您的测量结果太粗糙,无法准确跟踪线程堆栈内存消耗。它测量无法与其他进程共享的虚拟内存量。 .NET进程中唯一可共享的内存是代码,本机Windows DLL,CLR,抖动以及ngen.exe生成的任何本机映像(通常只有.NET框架程序集)。

其他一切都是私人记忆。 Jitted代码,加载器堆和垃圾收集堆是主要的块。这就是抛弃它,垃圾收集器会在可能的情况下缩小虚拟内存分配。

您可以使用SysInternals的VMMap实用程序更好地了解虚拟内存使用情况。你会淹没在细节中,但它会将线程堆栈显示为一个单独的类别。