18

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

我正在使用:

Process.GetCurrentProcess().PrivateMemorySize64

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

然后是“峰值”:我猜它只是存储这些最后一个所取的最大值。

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

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

这个进程基本上会保存一堆列表来记忆正在发生的事情,而其他进程与之通信并查询它的东西。我预计将在其中运行的服务器需要大量 RAM,因此我会随着时间的推移查询这些数据,以便与它保存在其中的列表的大小相比能够估计 RAM 需求。

所以......我应该使用哪一个,为什么?

4

7 回答 7

14

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

GC.GetTotalMemory(true)

如果您想知道您的进程在 Windows 中使用了什么(TaskManager 中的 VM 大小列),请尝试:

Process.GetCurrentProcess().PrivateMemorySize64

如果您想知道您的进程在 RAM 中(而不是在页面文件中)(TaskManager 中的内存使用列),请尝试:

Process.GetCurrentProcess().WorkingSet64

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

于 2008-08-27T20:23:11.090 回答
8

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

http://shsc.info/WindowsMemoryManagement

我的简短结论是:

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

  • Virtual Bytes = Private Bytes,加上与其他进程共享的用于加载的 DLL 等的空间。

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

感谢你的帮助!

于 2008-08-27T20:37:20.027 回答
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);
}
于 2008-11-14T08:13:55.023 回答
3

为了获得任务管理器提供的价值,我向 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();
    }`
于 2012-02-10T06:24:33.670 回答
1

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

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

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

鉴于上述情况,这里有一些方法可以测量 C# 中的内存使用情况:

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

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

3) Process.WorkingSet64():返回进程使用的所有私有的、加载的内存——托管或非托管

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

于 2018-11-13T21:52:41.623 回答
0

工作集不是一个好用的属性。根据我的收集,它包括进程可以接触的所有内容,甚至是由多个进程共享的库,因此您会在该计数器中看到重复计算的字节数。私有内存是一个更好的计数器。

于 2008-08-27T20:28:23.760 回答
0

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

于 2008-08-27T20:43:45.550 回答