1.PerformanceCounter有很多Category,监控进程时Category为Process。它下面有一些windows已实现的PerformanceCounter
public static void GetCounterNameValueList(string CategoryName, string instanceName)
{
string[] instanceNames;
ArrayList counters = new ArrayList();
PerformanceCounterCategory mycat = new PerformanceCounterCategory(CategoryName);
try
{
counters.AddRange(mycat.GetCounters(instanceName));
foreach (PerformanceCounter counter in counters)
{
Console.WriteLine(string.Format("{0,-30}:{1,20}", counter.CounterName, counter.RawValue));
}
}
catch (Exception)
{
Console.WriteLine("Unable to list the counters for this category");
}
}
输出:
% Processor Time : 404226406250
% User Time : 388479531250
% Privileged Time : 15746875000
Virtual Bytes Peak : 1362882560
Virtual Bytes : 1222418432
Page Faults/sec : 423652248
Working Set Peak : 741462016
Working Set : 613257216
Page File Bytes Peak : 713129984
Page File Bytes : 546553856
Private Bytes : 546553856
Thread Count : 41
Priority Base : 8
Elapsed Time : 130114216825494053
ID Process : 4376
Creating Process ID : 3980
Pool Paged Bytes : 1098488
Pool Nonpaged Bytes : 154480
Handle Count : 1051
IO Read Operations/sec : 197726
IO Write Operations/sec : 777888
IO Data Operations/sec : 975614
IO Other Operations/sec : 4481054
IO Read Bytes/sec : 9662784036
IO Write Bytes/sec : 14714361072
IO Data Bytes/sec : 24377145108
IO Other Bytes/sec : 59853109
Working Set - Private : 458493952
2.内存值可以调用NextValue直接得到,但Cpu、IO是计数器,需要至少两个时间点的值来计算这段时间的平均值。
private static void PrintProcessInfo(string name) { PerformanceCounter PTCounter = new PerformanceCounter("Process", "% Processor Time", name); PerformanceCounter DiskReadCounter = new PerformanceCounter("Process", "IO Read Bytes/sec", name); PerformanceCounter DiskWriteCounter = new PerformanceCounter("Process", "IO Write Bytes/sec", name); CounterSample cpuSample1 = PTCounter.NextSample(); CounterSample diskReadSample1 = DiskReadCounter.NextSample(); CounterSample diskWriteSample1 = DiskWriteCounter.NextSample(); Thread.Sleep(1000); CounterSample cpuSample2 = PTCounter.NextSample(); CounterSample diskReadSample2 = DiskReadCounter.NextSample(); CounterSample diskWriteSample2 = DiskWriteCounter.NextSample(); Console.WriteLine(CounterSampleCalculator.ComputeCounterValue(cpuSample1, cpuSample2)); Console.WriteLine(CounterSampleCalculator.ComputeCounterValue(diskReadSample1, diskReadSample2)); Console.WriteLine(CounterSampleCalculator.ComputeCounterValue(diskWriteSample1, diskWriteSample2)/1024/1024 + " MByte/s"); //内存 //PerformanceCounter WSCounter = new PerformanceCounter("Process", "Working Set", name); PerformanceCounter WSCounter = new PerformanceCounter("Process", "Working Set - Private", name); Console.WriteLine("Working Set:" + ((double) WSCounter.NextValue()/1024/1024).ToString()); //内存最高值 PerformanceCounter MemeryCounter = new PerformanceCounter("Process", "Working Set Peak", name); Console.WriteLine("Working Set Peak:" + ((double) MemeryCounter.NextValue()/1024/1024).ToString()); }
3.PerformanceCounter 的构造方法,不能使用进程pid,只能用程序名,多个同名时,第一个是原名,第二个加#1,例如:firefox,firefox#1,firefox#2.....
4.一个完整的示例
using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Threading; using System.Timers; using Timer = System.Timers.Timer; namespace Logic { public class ProcessMonitor { private class ProcessCounterSamples { public CounterSample CpuSample; public CounterSample DiskReadSample; public CounterSample DiskWriteSample; public CounterSample DiskReadWriteSample; } private class ProcessInfo { public float CpuPercentage { get; set; } public float DiskRead { get; set; } public float DiskWrite { get; set; } public float DiskReadWrite { get; set; } public float Memory { get; set; } public float MemoryMax { get; set; } } private const int RowsOfBuffer = 10; private const float Mega = (float)1024 * 1024; private string filePath; private Timer timer; private ListmonitorResults; private object fileLock=new object(); private int timerCount; private ProcessCounterSamples lastSample; private PerformanceCounter cpuCounter; private PerformanceCounter diskReadCounter; private PerformanceCounter diskWriteCounter; private PerformanceCounter diskReadWriteCounter; private PerformanceCounter memoryCounter; private PerformanceCounter memoryMaxCounter; //processName:no path, no extension //statFilePath:absolute path, extension public ProcessMonitor(string processName, string statFilePath, int statInterval) { filePath = statFilePath; InitPerformanceCounter(processName); monitorResults=new List (); timer = new Timer(statInterval); timer.Elapsed += DoStatistics; } public void StartMonitor() { timer.Start(); } public void StopMonitor() { timer.Stop(); AppendSave(filePath); } private void DoStatistics(object sender, ElapsedEventArgs elapsedEventArgs) { int threadsLeft, dummy; ThreadPool.GetAvailableThreads(out threadsLeft, out dummy); if (threadsLeft < 2) return; ProcessInfo info = GetProcessInfo(); monitorResults.Add(info); if (timerCount % RowsOfBuffer == 0) AppendSave(filePath); } private void AppendSave(string fileName) { lock (fileLock) { using (StreamWriter sw = new StreamWriter(fileName, true)) { var list = monitorResults; monitorResults = new List (); foreach (ProcessInfo info in list) { sw.WriteLine("{0},{1},{2},{3},{4},{5}", info.CpuPercentage, info.Memory, info.MemoryMax, info.DiskRead, info.DiskWrite, info.DiskReadWrite); } sw.Close(); } } } private ProcessInfo GetProcessInfo() { ProcessInfo result = new ProcessInfo(); ProcessCounterSamples currentSample = new ProcessCounterSamples(); currentSample.CpuSample = cpuCounter.NextSample(); currentSample.DiskReadSample = diskReadCounter.NextSample(); currentSample.DiskWriteSample = diskWriteCounter.NextSample(); currentSample.DiskReadWriteSample = diskReadWriteCounter.NextSample(); if (lastSample == null) { result.CpuPercentage = 0f; result.DiskRead = 0f; result.DiskWrite = 0f; result.DiskReadWrite = 0f; } else { result.CpuPercentage = CounterSampleCalculator.ComputeCounterValue(lastSample.CpuSample, currentSample.CpuSample); result.DiskRead = CounterSampleCalculator.ComputeCounterValue(lastSample.DiskReadSample, currentSample.DiskReadSample) / Mega; result.DiskWrite = CounterSampleCalculator.ComputeCounterValue(lastSample.DiskWriteSample, currentSample.DiskWriteSample) / Mega; result.DiskReadWrite = CounterSampleCalculator.ComputeCounterValue(lastSample.DiskReadWriteSample, currentSample.DiskReadWriteSample) / Mega; } lastSample = currentSample; result.Memory = memoryCounter.NextValue() / Mega; result.MemoryMax = memoryMaxCounter.NextValue() / Mega; return result; } private void InitPerformanceCounter(string processName) { cpuCounter = new PerformanceCounter("Process", "% Processor Time", processName); diskReadCounter = new PerformanceCounter("Process", "IO Read Bytes/sec", processName); diskWriteCounter = new PerformanceCounter("Process", "IO Write Bytes/sec", processName); diskReadWriteCounter = new PerformanceCounter("Process", "IO Data Bytes/sec", processName); memoryCounter = new PerformanceCounter("Process", "Working Set - Private", processName);//memory memoryMaxCounter = new PerformanceCounter("Process", "Working Set Peak", processName);//memory peak } } }
调用:
ProcessMonitor monitor2 = new ProcessMonitor("firefox", "D:\\tempData\\tmp2.csv", 1000); monitor2.StartMonitor(); Thread.Sleep(21000); monitor2.StopMonitor();
-----------
附
用timer写法不正确,可能会造成多线程时计数器同时访问的情况,从而计算出很大的结果。
performanceCounter的访问可能需要管理员权限
http://openpdc.codeplex.com/discussions/247310
http://social.msdn.microsoft.com/Forums/zh-CN/vstswebtest/thread/c54247d9-6035-4d77-9293-e9986517e310