【发布时间】:2011-02-06 08:33:47
【问题描述】:
如何使用 C# 计算私有工作内存集?我有兴趣生成与taskmgr.exe 大致相同的数字。
我正在使用 Process 命名空间并使用 WorkingSet64 和 PrivateMemorySize64 等方法/数据,但这些数字有时会相差 100MB 或更多。
【问题讨论】:
标签: c# memory memory-management
如何使用 C# 计算私有工作内存集?我有兴趣生成与taskmgr.exe 大致相同的数字。
我正在使用 Process 命名空间并使用 WorkingSet64 和 PrivateMemorySize64 等方法/数据,但这些数字有时会相差 100MB 或更多。
【问题讨论】:
标签: c# memory memory-management
这是一个高度可变的数字,你无法计算它。 Windows 内存管理器不断将页面换入和换出 RAM。 TaskMgr.exe 从性能计数器中获取它。你可以像这样得到相同的数字:
using System;
using System.Diagnostics;
class Program {
static void Main(string[] args) {
string prcName = Process.GetCurrentProcess().ProcessName;
var counter = new PerformanceCounter("Process", "Working Set - Private", prcName);
Console.WriteLine("{0}K", counter.RawValue / 1024);
Console.ReadLine();
}
}
请注意,这个数字实际上并没有多大意义,当其他进程启动并竞争 RAM 时,它会下降。
【讨论】:
ProcessName 查找匹配的计数器实例是不够的。如果您有多个相同的进程(例如 svchost.exe),那么计数器名称将是“svchost#1”、“svchost#2”等。您需要通过“ID 进程”计数器进行匹配,这也是一部分进程类别,Process.ID.
对于未来的用户,这是我必须做的,以确保为可能有多个实例的进程获取私有工作集。我调用CurrentMemoryUsage,它从GetNameToUseForMemory 获取适当的进程名称。我发现这个循环很慢,即使我可以过滤掉结果。所以,这就是为什么您会看到 GetNameToUseForMemory 使用字典来缓存名称。
private static long CurrentMemoryUsage(Process proc)
{
long currentMemoryUsage;
var nameToUseForMemory = GetNameToUseForMemory(proc);
using (var procPerfCounter = new PerformanceCounter("Process", "Working Set - Private", nameToUseForMemory))
{
//KB is standard
currentMemoryUsage = procPerfCounter.RawValue/1024;
}
return currentMemoryUsage;
}
private static string GetNameToUseForMemory(Process proc)
{
if (processId2MemoryProcessName.ContainsKey(proc.Id))
return processId2MemoryProcessName[proc.Id];
var nameToUseForMemory = String.Empty;
var category = new PerformanceCounterCategory("Process");
var instanceNames = category.GetInstanceNames().Where(x => x.Contains(proc.ProcessName));
foreach (var instanceName in instanceNames)
{
using (var performanceCounter = new PerformanceCounter("Process", "ID Process", instanceName, true))
{
if (performanceCounter.RawValue != proc.Id)
continue;
nameToUseForMemory = instanceName;
break;
}
}
if(!processId2MemoryProcessName.ContainsKey(proc.Id))
processId2MemoryProcessName.Add(proc.Id, nameToUseForMemory);
return nameToUseForMemory;
}
【讨论】: