为什么我的线程似乎只占用不到1MB的内存?

3

我试图更好地掌握.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个回答

2
您可能想使用VirtualMemorySize64()而不是PrivateMemorySize64()
MS在此处写道:
每个新线程或纤程都会获得自己的堆栈空间,其中包括保留和最初分配的内存。保留内存大小表示虚拟内存中的总堆栈分配。[...] 最初分配的页面在被引用之前不会使用物理内存; [...]
由于OP示例代码中的线程除了等待信号外什么也不做,它们(堆栈)的内存不使用物理内存,因此不会被PrivateMemorySize64()考虑在内。

1

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

其他所有内容都是私有内存。Jitted代码、加载器堆和垃圾回收堆是主要的块。这就是导致问题的原因,垃圾回收器会在可以时缩小虚拟内存分配。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接