【问题标题】:How to measure memory usage with C# (as we can do in Java)? [duplicate]如何使用 C# 测量内存使用情况(就像我们在 Java 中所做的那样)? [复制]
【发布时间】:2012-03-13 09:07:12
【问题描述】:

我正在尝试在 C# 程序中测量内存使用情况。

我想知道这个 Java 函数的 C# 等价物:

ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getCommitted()

表示为堆分配的总内存。我需要这个来知道为我的 C# 程序分配的内存的总大小。

然后在 Java 中,我可以通过以下方式获取已使用的内存:

ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed()

目前我在 C# 中使用它来获取已用内存:

Process_Memory = MyProcess.PrivateMemorySize64;

但我不完全确定它是等价的。

那么在简历中,我怎样才能获得我的 C# 应用程序的总分配空间和当前的使用情况t

编辑:

根据答案和进一步的研究,我确定了这一点:

当前正在使用的内存

System.GC.GetTotalMemory(false);

给出当前在托管内存中分配的字节数。 (http://msdn.microsoft.com/fr-fr/library/system.gc.gettotalmemory.aspx)

这个方法返回一个低值,我很确定它并不能真正代表所有正在使用的内存,因为我可以在 Java 中使用getUsed()。在 Java 中,同一应用程序使用的内存从 5MB 开始,最大到 125MB。使用 C#,我通过上述方法从 1 到 5 MB。

看来:

MyProcess.PrivateMemorySize64; // return ~=25MB

MyProcess.WorkingSet64;  //return ~=20MB

给出所有正在使用的内存的更准确值。但我不知道我应该使用哪个...

对于全局分配内存this article建议使用:

Process_MemoryEnd1 = MyProcess.VirtualMemorySize64;

它在程序中返回总是相同的值,大​​约 169MB,与 Java 相比似乎公平:从 64MB 到最大 170MB

我仍在寻找一个准确的答案,但我发现的所有内容都非常模糊,而且我对 Windows 内存管理不是很熟悉,我不确定是否了解我找到的文档:/

【问题讨论】:

    标签: c# java memory memory-management


    【解决方案1】:

    这是一种方法,使用 GC:

        public void Test()
        {
            long kbAtExecution = GC.GetTotalMemory(false) / 1024;
    
            // do stuff that uses memory here 
    
            long kbAfter1 = GC.GetTotalMemory(false) / 1024;
            long kbAfter2 = GC.GetTotalMemory(true) / 1024;
    
            Console.WriteLine(kbAtExecution + " Started with this kb.");
            Console.WriteLine(kbAfter1 + " After the test.");
            Console.WriteLine(kbAfter1 - kbAtExecution + " Amt. Added.");
            Console.WriteLine(kbAfter2 + " Amt. After Collection");
            Console.WriteLine(kbAfter2 - kbAfter1 + " Amt. Collected by GC.");         
        }
    

    或者使用 System.Diagnostics.PerformanceCounter 获取工作集信息:

    PerformanceCounter performanceCounter = new PerformanceCounter();
    
    performanceCounter.CategoryName = "Process";
    
    performanceCounter.CounterName = "Working Set";
    
    performanceCounter.InstanceName = Process.GetCurrentProcess().ProcessName;
    
    Console.WriteLine(((uint)performanceCounter.NextValue()/1024).ToString("N0"));
    

    【讨论】:

    • 感谢您的回答。因此,正如文档所说,GC.GetTotalMemory(false) 返回托管内存中当前分配的字节数。我认为它可能相当于java中的getUse()。但是我如何分配整个空间? `System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64` 是否代表该值?
    • 对于第二个解决方案,它提出了System.InvalidOperationException
    • @alain.janinm,不知道为什么。在我的系统上工作。错误或内部异常是什么意思?
    • Heu 问题是 VS 用法语给出错误,所以我会尝试翻译:Impossible to load the data of counter name, because an index is not valid '' as been read from register.跨度>
    • 使用基于 GC 的方法,我得到的相同代码块的数字非常不一致(大约 16 倍的变化)。通过在它之前添加GC.Collect();GC.WaitForPendingFinalizers();,我能够获得更多更一致的测量结果。
    【解决方案2】:

    GC 静态类提供所有此类信息。

    你可能在GC.GetTotalMemory()之后。

    编辑:

    我相信尝试根据当前根对象来锻炼您的内存占用。 如果您想要为进程分配的总大小(即包括空闲缓冲区),请使用 Process 类。例如:

    Process.GetCurrentProcess().WorkingSet64;
    

    【讨论】:

    • 是的,我知道这一点,但它给出了托管堆中对象的实际大小,这是一个低值。我认为这不能代表所有分配的内存。
    • 那么我相信如果你想要原始分配的内存(即不考虑任何托管 GC 功能),你只需要使用 Process 类的所有这些属性。 PagedMemorySize64PrivateMemorySize64
    • 谢谢,所以我想如果我只想要进程分配的总内存PrivateMemorySize64 就足够了。我不明白什么是分页内存...
    • 这是一个边缘案例。如果物理 RAM 已满,操作系统将使用一块硬盘作为“内存”,称为“虚拟内存”。所以如果你真的很迂腐,想要总数,你真的应该把它们都加起来,以防万一。我不确定WorkingSet64 是否考虑了虚拟内存。 MSDN 说“WorkingSet64:获取为相关进程分配的物理内存量。”
    • 好的,所以我想要添加的总分配内存NonpagedSystemMemorySize64 + PagedMemorySize64 + PagedSystemMemorySize64 + PrivateMemorySize64 + WorkingSet64 ?
    猜你喜欢
    • 1970-01-01
    • 2021-09-02
    • 2011-09-13
    • 2013-10-15
    • 1970-01-01
    • 1970-01-01
    • 2012-11-23
    • 2014-05-11
    • 2012-12-07
    相关资源
    最近更新 更多