进程内存大小 - 不同的计数器

时间:2008-08-27 20:05:23

标签: c# .net memory process diagnostics

我正在试图找出我自己的.Net服务器进程正在使用多少内存(用于监视和记录目的)。

我正在使用:

Process.GetCurrentProcess().PrivateMemorySize64

但是,Process对象有几个不同的属性,让我可以读取使用的内存空间: 分页,非分页,PagedSystem,NonPagedSystem,私有,虚拟,WorkingSet

然后是“峰值”:我猜测它只是存储了最后一次拍摄的最大值。

阅读每个属性的MSDN定义对我来说并没有太大帮助。我必须承认我对内存管理方式的了解(就分页和虚拟内容而言)非常有限。

所以我的问题显然是“我应该使用哪一个?”,我知道答案是“它取决于”。

这个过程基本上会在内存中保存一堆列表,而其他进程与它进行通信并查询它。我期待运行它的服务器需要大量的RAM,因此我会随着时间的推移查询这些数据,以便能够估计RAM要求与其保留的列表大小相比。

那么......我应该使用哪一个?为什么?

7 个答案:

答案 0 :(得分:14)

如果您想了解GC使用的程度,请尝试:

GC.GetTotalMemory(true)

如果您想知道您的进程从Windows使用的内容(TaskManager中的VM Size列),请尝试:

Process.GetCurrentProcess().PrivateMemorySize64

如果你想知道你的进程在RAM中的位置(而不是在页面文件中)(TaskManager中的Mem Usage列),请尝试:

Process.GetCurrentProcess().WorkingSet64

有关不同种类内存的更多说明,请参阅here

答案 1 :(得分:6)

好的,我通过Google找到了Lars提到的同一页面,我相信对于那些不太了解记忆效果的人(比如我)来说,这是一个很好的解释。

http://shsc.info/WindowsMemoryManagement

我的简短结论是:

  • Private Bytes =我的进程请求存储数据的内存。其中一些可能会被分页到磁盘。这是我要找的信息。

  • 虚拟字节数=私有字节数,加上与加载的DLL等其他进程共享的空间

  • Working Set =我的进程的所有内存中尚未被分页到磁盘的部分。因此,分页到磁盘的数量应为(虚拟 - 工作集)。

感谢大家的帮助!

答案 2 :(得分:5)

如果要使用Windows Vista任务管理器中显示的“内存(专用工作集)”,它等同于Process Explorer“WS Private Bytes”,则代码如下所示。可能最好将此无限循环抛出到线程/后台任务中以获取实时统计信息。

using System.Threading;
using System.Diagnostics;

//namespace...class...method

Process thisProc = Process.GetCurrentProcess();
PerformanceCounter PC = new PerformanceCounter();

PC.CategoryName = "Process";
PC.CounterName = "Working Set - Private";
PC.InstanceName = thisProc.ProcessName;

while (true)
{
 String privMemory = (PC.NextValue()/1000).ToString()+"KB (Private Bytes)";
 //Do something with string privMemory

 Thread.Sleep(1000);
}

答案 3 :(得分:2)

为了获得任务管理器给出的价值,我的帽子已经转到Mike Regan的解决方案上面了。但是,有一个变化:它不是:perfCounter.NextValue()/1000;而是perfCounter.NextValue()/1024;(即真正的千字节)。这给出了您在任务管理器中看到的确切值。

以下是显示“内存使用情况”的完整解决方案。 (WPF或WinForms应用程序中的一个简单方式(任务管理器,如给定的)(在这种情况下,只需在标题中)。只需在新的Window构造函数中调用此方法:

    private void DisplayMemoryUsageInTitleAsync()
    {
        origWindowTitle = this.Title; // set WinForms or WPF Window Title to field
        BackgroundWorker wrkr = new BackgroundWorker();
        wrkr.WorkerReportsProgress = true;

        wrkr.DoWork += (object sender, DoWorkEventArgs e) => {
            Process currProcess = Process.GetCurrentProcess();
            PerformanceCounter perfCntr = new PerformanceCounter();
            perfCntr.CategoryName = "Process";
            perfCntr.CounterName = "Working Set - Private";
            perfCntr.InstanceName = currProcess.ProcessName;

            while (true)
            {
                int value = (int)perfCntr.NextValue() / 1024;
                string privateMemoryStr = value.ToString("n0") + "KB [Private Bytes]";
                wrkr.ReportProgress(0, privateMemoryStr);
                Thread.Sleep(1000);
            }
        };

        wrkr.ProgressChanged += (object sender, ProgressChangedEventArgs e) => {
            string val = e.UserState as string;
            if (!string.IsNullOrEmpty(val))
                this.Title = string.Format(@"{0}   ({1})", origWindowTitle, val);
        };

        wrkr.RunWorkerAsync();
    }`

答案 4 :(得分:0)

工作集不是一个好用的属性。从我收集的内容中,它包括进程可以触及的所有内容,甚至是由多个进程共享的库,因此您在该计数器中看到了双重计数的字节。私人记忆是一个更好的反击。

答案 5 :(得分:0)

我建议还要监控网页故障发生的频率。当您尝试访问已从物理内存移动到交换文件的某些数据时,会发生页面故障,系统必须先从磁盘读取页面,然后才能访问此数据。

答案 6 :(得分:0)

这是一个公平的描述吗?我想与我的团队分享此信息,所以请告诉我它是否不正确(或不完整):

在C#中,有几种方法可以询问我的进程正在使用多少内存。

  • 可以(通过CLR)管理已分配的内存,也可以不受管理。
  • 已分配的内存可以是虚拟的(存储在磁盘上),也可以是已加载的(进入RAM页面)
  • 已分配的内存可以是私有的(仅由进程使用)或共享的(例如,属于其他进程正在引用的DLL)。

鉴于上述情况,以下是一些在C#中测量内存使用情况的方法:

1)Process.VirtualMemorySize64():返回进程使用的所有内存-托管或非托管,虚拟或加载,私有或共享。

2)Process.PrivateMemorySize64():返回进程使用的所有私有内存-托管或非托管,虚拟或已加载。

3)Process.WorkingSet64():返回进程使用的所有私有,已加载内存-托管还是非托管

4)GC.GetTotalMemory():返回垃圾回收器正在监视的托管内存量。