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

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

我正在使用:

Process.GetCurrentProcess().PrivateMemorySize64 

但是,Process对象有几个不同的属性,让我可以读取使用的内存空间:Paged,NonPaged,PagedSystem,NonPagedSystem,Private,Virtual,WorkingSet

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

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

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

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

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

如果您想知道GC使用了多少尝试:

 GC.GetTotalMemory(true) 

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

 Process.GetCurrentProcess().PrivateMemorySize64 

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

 Process.GetCurrentProcess().WorkingSet64 

有关不同类型的内存的更多说明,请参见此处 。

如果要使用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); } 

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

http://shsc.info/WindowsMemoryManagement

我的简短结论是:

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

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

  • Working Set =我的进程的所有内存中尚未分页到磁盘的部分。 所以分页到磁盘的数量应该是(虚拟 – 工作集)。

感谢你的帮助!

为了获得任务管理器给出的价值,我的帽子是迈克里根的解决方案。 然而,一个改变:它不是: 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(); }` 

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

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