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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31096/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 08:26:00  来源:igfitidea点击:

Process Memory Size - Different Counters

提问by Daniel Magliola

I'm trying to find out how much memory my own .Net server process is using (for monitoring and logging purposes).

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

I'm using:

我正在使用:

Process.GetCurrentProcess().PrivateMemorySize64

However, the Process object has several different properties that let me read the memory space used: Paged, NonPaged, PagedSystem, NonPagedSystem, Private, Virtual, WorkingSet

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

and then the "peaks": which i'm guessing just store the maximum values these last ones ever took.

然后是“峰值”:我猜它只是存储这些最后一个曾经使用过的最大值。

Reading through the MSDN definition of each property hasn't proved too helpful for me. I have to admit my knowledge regarding how memory is managed (as far as paging and virtual goes) is very limited.

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

So my question is obviously "which one should I use?", and I know the answer is "it depends".

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

This process will basically hold a bunch of lists in memory of things that are going on, while other processes communicate with it and query it for stuff. I'm expecting the server where this will run on to require lots of RAM, and so i'm querying this data over time to be able to estimate RAM requirements when compared to the sizes of the lists it keeps inside.

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

So... Which one should I use and why?

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

采纳答案by Lars Truijens

If you want to know how much the GC uses try:

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

GC.GetTotalMemory(true)

If you want to know what your process uses from Windows (VM Size column in TaskManager) try:

如果您想从 Windows(TaskManager 中的 VM Size 列)了解您的进程使用了​​什么,请尝试:

Process.GetCurrentProcess().PrivateMemorySize64

If you want to know what your process has in RAM (as opposed to in the pagefile) (Mem Usage column in TaskManager) try:

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

Process.GetCurrentProcess().WorkingSet64

See herefor more explanation on the different sorts of memory.

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

回答by OwenP

Working set isn't a good property to use. From what I gather, it includes everything the process can touch, even libraries shared by several processes, so you're seeing double-counted bytes in that counter. Private memory is a much better counter to look at.

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

回答by Daniel Magliola

OK, I found through Google the same page that Lars mentioned, and I believe it's a great explanation for people that don't quite know how memory works (like me).

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

http://shsc.info/WindowsMemoryManagement

http://shsc.info/WindowsMemoryManagement

My short conclusion was:

我的简短结论是:

  • Private Bytes = The Memory my process has requested to store data. Some of it may be paged to disk or not. This is the information I was looking for.

  • Virtual Bytes = The Private Bytes, plus the space shared with other processes for loaded DLLs, etc.

  • Working Set = The portion of ALL the memory of my process that has not been paged to disk. So the amount paged to disk should be (Virtual - Working Set).

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

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

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

Thanks all for your help!

感谢你的帮助!

回答by Micha? Piaskowski

I'd suggest to also monitor how often pagefaults happen. A pagefault happens when you try to access some data that have been moved from physical memory to swap file and system has to read page from disk before you can access this data.

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

回答by Michael Regan

If you want to use the "Memory (Private Working Set)" as shown in Windows Vista task manager, which is the equivalent of Process Explorer "WS Private Bytes", here is the code. Probably best to throw this infinite loop in a thread/background task for real-time stats.

如果您想使用 Windows Vista 任务管理器中显示的“内存(私有工作集)”,它相当于进程资源管理器的“WS 私有字节”,这里是代码。最好在线程/后台任务中抛出这个无限循环以获得实时统计数据。

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);
}

回答by Nicholas Petersen

To get the value that Task Manager gives, my hat's off to Mike Regan's solution above. However, one change: it is not: perfCounter.NextValue()/1000;but perfCounter.NextValue()/1024;(i.e. a real kilobyte). This gives the exact value you see in Task Manager.

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

Following is a full solution for displaying the 'memory usage' (Task manager's, as given) in a simple way in your WPF or WinForms app (in this case, simply in the title). Just call this method within the new Window constructor:

以下是在 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();
    }`

回答by Phoeniceus Agelaius

Is this a fair description? I'd like to share this with my team so please let me know if it is incorrect (or incomplete):

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

There are several ways in C# to ask how much memory my process is using.

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

  • Allocated memory can be managed (by the CLR) or unmanaged.
  • Allocated memory can be virtual (stored on disk) or loaded (into RAM pages)
  • Allocated memory can be private (used only by the process) or shared (e.g. belonging to a DLL that other processes are referencing).
  • 分配的内存可以是托管的(由 CLR),也可以是非托管的。
  • 分配的内存可以是虚拟的(存储在磁盘上)或加载的(到 RAM 页面中)
  • 分配的内存可以是私有的(仅由进程使用)或共享的(例如属于其他进程正在引用的 DLL)。

Given the above, here are some ways to measure memory usage in C#:

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

1) Process.VirtualMemorySize64(): returns all the memory used by a process - managed or unmanaged, virtual or loaded, private or shared.

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

2) Process.PrivateMemorySize64(): returns all the private memory used by a process - managed or unmanaged, virtual or loaded.

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

3) Process.WorkingSet64(): returns all the private, loaded memory used by a process - managed or unmanaged

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

4) GC.GetTotalMemory(): returns the amount of managed memory being watched by the garbage collector.

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