【问题标题】:Process Memory Size - Different Counters进程内存大小 - 不同的计数器
【发布时间】:2010-09-07 01:29:57
【问题描述】:

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

我正在使用:

Process.GetCurrentProcess().PrivateMemorySize64

但是,Process 对象有几个不同的属性,可以让我读取使用的内存空间: 分页、非分页、分页系统、非分页系统、私有、虚拟、工作集

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

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

所以我的问题显然是“我应该使用哪一个?”,而我知道答案是“视情况而定”。

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

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

【问题讨论】:

    标签: c# .net memory process diagnostics


    【解决方案1】:

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

    GC.GetTotalMemory(true)
    

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

    Process.GetCurrentProcess().PrivateMemorySize64
    

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

    Process.GetCurrentProcess().WorkingSet64
    

    请参阅here 了解有关不同类型内存的更多说明。

    【讨论】:

    • 看起来它们都没有显示来自 TaskManager 或 VS 诊断的内存
    【解决方案2】:

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

    http://shsc.info/WindowsMemoryManagement

    我的简短结论是:

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

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

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

    感谢大家的帮助!

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      为了获得任务管理器提供的价值,我对 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();
          }`
      

      【讨论】:

      • 这是我遇到的最准确的一个。我想匹配任务管理器显示的内容。
      【解决方案5】:

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

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

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

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

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

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

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

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

      【讨论】:

        【解决方案6】:

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

        【讨论】:

          【解决方案7】:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-10-11
            • 1970-01-01
            • 2010-12-12
            • 2011-12-28
            相关资源
            最近更新 更多