Creating a new System.Diagnostics.PerformanceCounter is very slow - c#

I have a simple monitoring application that is getting some values from PerfMon counters. Even when testing on the local machine, it is taking over 30 seconds to create a new PerformanceCounter object.
using System;
using System.Diagnostics;
namespace test_slow_perfmon
{
class Program
{
static void Main(string[] args)
{
Stopwatch w = new Stopwatch();
w.Start();
PerformanceCounter c = new PerformanceCounter("PhysicalDisk", "Avg. Disk Read Queue Length", "_Total", "localhost");
w.Stop();
Console.WriteLine(string.Format("Creating a counter took {0}ms", w.Elapsed.TotalMilliseconds));
}
}
}
Output from that indicates over 32s to create each counter.
What can I do (if anything) to speed up the creation of the counters?

30 seconds sounds to me suspiciously like a timeout, indicating to me that this could be some sort of network issue.
Try creating your perfmon counter using the constructor that doesn't specify a hostname and see if that helps:
PerformanceCounter c = new PerformanceCounter("PhysicalDisk", "Avg. Disk Read Queue Length", "_Total");

Related

c# CPU and Memory Monitor Console app keeps warning me that mu CPU load is at 100%

I'm assuming I have found myself some sort of a nasty bug.
I have recently tried to create a console application in c# that prints the CPU Load & available memory every second. Whilst this goes on I have made sure that the application only warns about the CPU usage when the CPU Load goes over 80 percent. With a much more serious warning at 100% as you will see.
However, when i run the application it continually warns me that the CPU is at 100%, even though I know it shouldn't be running anywhere near that. I downloaded CPU Burn In to test the app and push the CPU to 100%, However I am 100 percent sure that it has been disabled the whole time.
I will post my code below.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Threading;
using System.Speech.Synthesis;
namespace CpuandMemoryMonitor
{
class Program
{
/// <summary>
/// Entry Point into the Program | Program: CPU & Memory Monitor |By:
Andrew.
/// </summary>
///
static void Main(string[] args)
{
#region My performance Counters
// This will greet the user in the default voice
SpeechSynthesizer synth = new SpeechSynthesizer();
synth.Speak("Welcome to the CPU and Memory Monitor");
// This will pull the current CPU load in percentage.
PerformanceCounter perfCpuCount = new PerformanceCounter("Processor Information", "% Processor Time", "_Total");
// This will pull the current available Memory in Megabytes
PerformanceCounter perfMemCount = new PerformanceCounter("Memory", "Available MBytes");
// This will give us system uptime (in Seconds)
PerformanceCounter perfUptimecount = new PerformanceCounter("System", "System Up Time");
#endregion
#region Perfromance Counters Program Loop
//Infinite While Loop.
while (true)
{
// Get the current perforance counter values
int currentcpupercentage = (int)perfCpuCount.NextValue();
int currentavailablememory = (int)perfMemCount.NextValue();
//Print the performance counter values to the console screen
Console.WriteLine("CPU Load: {0}%", currentcpupercentage);
Console.WriteLine("Available Memory: {0}MB", currentavailablememory);
// Speech synthasiser warns user when CPU Load is above 80 percent
if (currentcpupercentage > 80)
{
///If CPU Load is at 100 % Warn the user in a a female voice!
if (currentcpupercentage == 100)
{
synth.SelectVoiceByHints(VoiceGender.Female);
string cpuLoadVocalMessage = String.Format("Oh dear! You're CPU is about to catch on Fire!");
synth.Speak(cpuLoadVocalMessage);
}
else
//If CPU Load is at 80 % Warn the user in a a male voice!
{
synth.SelectVoiceByHints(VoiceGender.Male);
string cpuLoadVocalMessage = String.Format("The Current Cpu Load is {0}", currentcpupercentage);
synth.Speak(cpuLoadVocalMessage);
}
// Speech synthasiser warns user when memory is less then 1 gigabyte
if (currentavailablememory < 1024)
{
// If CPU Load is at 100 % Warn the user ina a female voice!
string memavailableVocalMessage = string.Format("You currently have {0} gigabytes of memory available", currentavailablememory / 1024);
synth.Speak(memavailableVocalMessage);
}
//Sleep for 1 second
Thread.Sleep(1000);
}
#endregion
}
}
}
}
You have an infinite loop, if you have an infinite loop the computer will run the code continuously. As others have pointed out in the comments, you should use some form of timer in order to only poll at specific intervals. Even better you can use a WMI Event watcher to get called only when the alarm is hit.
Google WMI Events or read things like;
https://msdn.microsoft.com/en-us/library/aa393013(v=vs.85).aspx

How to get performance data?

I want to get the performance data like in the performance tab in the task manager window.
I got this code:
using (PerformanceCounter pCounter = new PerformanceCounter())
{
pCounter.CategoryName = "Processor"; //this get me the cpu usage
pCounter.CounterName = "% Processor Time";
pCounter.InstanceName = "_Total";
// will always start at 0
pCounter.NextValue();
System.Threading.Thread.Sleep(1000);
//now matches task manager reading
float cpuUsage = pCounter.NextValue();
pCounter.CategoryName = "Memory";
pCounter.CounterName = "Available MBytes"; //this gets me the available memory
pCounter.InstanceName = string.Empty;
}
I also need:
The up time (time the server is active HH:mm:ss)
Number of processes
Number of threads
Ethernet usage
I have no idea how to get this data...
The .net framework provides the System.Diagnostics class with a plethora of methods to access system info including performance data.
https://msdn.microsoft.com/en-us/library/vstudio/System.Diagnostics%28v=vs.90%29.aspx

How to use Performance Counter or Process class correctly in C# to get memory usage of current process?

According to How to use .NET PerformanceCounter to track memory and CPU usage per process? PerformanceCounter should give me the number of memory usage of a given process.
According to MSDN, Process instance may also give me more or less the same number.
In order to verify my assumptions, I wrote the following code:
class Program
{
static Process process = Process.GetCurrentProcess();
static PerformanceCounter privateBytesCounter = new PerformanceCounter("Process", "Private Bytes", process.ProcessName);
static PerformanceCounter workingSetCounter = new PerformanceCounter("Process", "Working Set", process.ProcessName);
static void Main(string[] args)
{
GetMeasure();
Console.WriteLine("\nPress enter to allocate great amount of memory");
Console.ReadLine();
int[] arr = new int[10000000];
for (int i = 0; i < arr.Length; i++)
{
arr[i] = i;
}
GetMeasure();
privateBytesCounter.Dispose();
workingSetCounter.Dispose();
Console.ReadKey();
}
private static void GetMeasure()
{
Console.WriteLine("{0,38} {1,20}", "Private bytes", "working set");
Console.WriteLine("process data{0,23} {1,20}", process.PrivateMemorySize64 / 1024, process.WorkingSet64 / 1024);
Console.WriteLine("PerformanceCounter data{0,12} {1,20}", privateBytesCounter.NextValue() / 1024, workingSetCounter.NextValue() / 1024);
}
}
The output looks like
Private bytes working set
process data 22880 17516
PerformanceCounter data 21608 15608
Press enter to allocate great amount of memory
Private bytes working set
process data 22880 17516
PerformanceCounter data 21608 15608
Exactly the same! In the contrast, private bytes shown in Process Explorer increased from 32732 to 63620.
So am I doing something wrong?
You have to tell your process instance it should refresh its cached data. Data is not gathered each time you access to a property for performance purposes. You have to manually demand the data update.
private static void GetMeasure()
{
process.Refresh(); // Updates process information
Console.WriteLine("{0,38} {1,20}", "Private bytes", "working set");
Console.WriteLine("process data{0,23} {1,20}", process.PrivateMemorySize64 / 1024, process.WorkingSet64 / 1024);
Console.WriteLine("PerformanceCounter data{0,12} {1,20}", privateBytesCounter.NextValue() / 1024, workingSetCounter.NextValue() / 1024);
}
That's for your process.
For performance counters, NextValue() is supposed to retrieve a new fresh data each time, so I can't explain why it doesn't on your machine. On mine it works fine.
EDIT:
With the process.Refresh() added, here's what I get:
Private bytes working set
process data 25596 22932
PerformanceCounter data 26172 23600
Press enter to allocate great amount of memory
Private bytes working set
process data 65704 61848
PerformanceCounter data 65828 61880
Caution: my memory profiler (.NET Memory Profiler) revealed that Process.Refresh() allocates a significant chunk of memory on a temporary basis, so keep this in mind if you're reading your performance counters on a regular basis by using a timer.

Performance counter C# and HyperPi

I am in attempt to get CPU Usage reading correctly. The code below is executed without problem but I can't get CPU Usage reading at 100% when I run Hyper PI which is a multicores CPU stress test. What did I do wrong? Thank you for your time.
Alternatively, is it possible to get CPU Usage readings from WMI?
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace TestHarnessCPUUsage
{
class Program
{
static void Main(string[] args)
{
PerformanceCounter cpuCounter;
PerformanceCounter ramCounter;
cpuCounter = new PerformanceCounter();
cpuCounter.CategoryName = "Processor";
cpuCounter.CounterName = "% Processor Time";
cpuCounter.InstanceName = "_Total";
ramCounter = new PerformanceCounter("Memory", "Available MBytes");
ramCounter.CategoryName = "Memory";
ramCounter.CounterName = "Available MBytes";
Console.WriteLine(cpuCounter.NextValue()
+ "%");
Console.WriteLine(ramCounter.NextValue()
+ "MB");
Console.ReadKey();
}
}
}
That's the kind of perf counter you have to sample yourself. Processor time is a measure over an interval. It tells you how long the processor was turned off, versus it running at 100%. The ratio is the value you get, times 100. One second is the typical interval time, like TaskMgr.exe and Perfmon uses. The smaller you make the interval, the 'noisier' it gets. Down to one sample, like you did, where you get no data at all since there wasn't an interval. Fix:
using System;
using System.Diagnostics;
class Program {
static void Main(string[] args) {
PerformanceCounter cpuCounter;
cpuCounter = new PerformanceCounter();
cpuCounter.CategoryName = "Processor";
cpuCounter.CounterName = "% Processor Time";
cpuCounter.InstanceName = "_Total";
cpuCounter.NextValue();
while (!Console.KeyAvailable) {
System.Threading.Thread.Sleep(1000);
Console.WriteLine(cpuCounter.NextValue());
}
}
}

How do I get the CPU speed and total physical ram in C#?

I need a simple way of checking how much ram and fast the CPU of the host PC is. I tried WMI however the code I'm using
private long getCPU()
{
ManagementClass mObject = new ManagementClass("Win32_Processor");
mObject.Get();
return (long)mObject.Properties["MaxClockSpeed"].Value;
}
Throws a null reference exception. Furthermore, WMI queries are a bit slow and I need to make a few to get all the specs. Is there a better way?
http://dotnet-snippets.com/dns/get-the-cpu-speed-in-mhz-SID575.aspx
using System.Management;
public uint CPUSpeed()
{
ManagementObject Mo = new ManagementObject("Win32_Processor.DeviceID='CPU0'");
uint sp = (uint)(Mo["CurrentClockSpeed"]);
Mo.Dispose();
return sp;
}
RAM can be found in this SO question: How do you get total amount of RAM the computer has?
You should use PerformanceCounter class in System.Diagnostics
PerformanceCounter cpuCounter;
PerformanceCounter ramCounter;
cpuCounter = new PerformanceCounter();
cpuCounter.CategoryName = "Processor";
cpuCounter.CounterName = "% Processor Time";
cpuCounter.InstanceName = "_Total";
ramCounter = new PerformanceCounter("Memory", "Available MBytes");
public string getCurrentCpuUsage(){
cpuCounter.NextValue()+"%";
}
public string getAvailableRAM(){
ramCounter.NextValue()+"MB";
}
Much about the processor including its speed in Mhz is available under HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor
I'm running 2 Win7x64 pcs and for some reason the WMI query shows a vague number the first time I run the code and the correct processor speed the second time I run it?
When it comes to performance counters, I did work a LOT with the network counters and got in accurate results and eventually had to find a better solution, so I dont trust them!

Categories