3

我试图更好地掌握 .NET 线程模型。我多次听到并阅读(最近一次是在观看此视频时:AppFabric.tv - 与 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();
    }
}

任何见解将不胜感激。

4

2 回答 2

2

您可能喜欢使用VirtualMemorySize64()but PrivateMemorySize64()

女士在这里写道

每个新线程或纤程都会收到自己的堆栈空间,包括保留的和最初提交的内存。保留内存大小表示虚拟内存中的总堆栈分配。[...] 最初提交的页面在被引用之前不会使用物理内存;[...]

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

于 2012-10-27T15:33:55.660 回答
1

您的测量太粗略,无法准确跟踪线程堆栈内存消耗。它测量不能与另一个进程共享的虚拟内存量。.NET 进程中唯一可共享的内存是代码、本机 Windows DLL、CLR、抖动和任何由 ​​ngen.exe 生成的本机图像(通常只有 .NET 框架程序集)。

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

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

于 2012-10-27T16:08:40.480 回答