I'm trying to access the performance counters located in ".NET CLR Memory category" through C# using the PerformanceCounter class. However a cannot instantiate the categories with what I would expect was the correct category/counter name
new PerformanceCounter(".NET CLR Memory", "# bytes in all heaps", Process.GetCurrentProcess().ProcessName);
I tried looping through categories and counters using the following code
string[] categories = PerformanceCounterCategory.GetCategories().Select(c => c.CategoryName).OrderBy(s => s).ToArray();
string toInspect = string.Join(",\r\n", categories);
System.Text.StringBuilder interestingToInspect = new System.Text.StringBuilder();
string[] interestingCategories = categories.Where(s => s.StartsWith(".NET") || s.Contains("Memory")).ToArray();
foreach (string interestingCategory in interestingCategories)
{
PerformanceCounterCategory cat = new PerformanceCounterCategory(interestingCategory);
foreach (PerformanceCounter counter in cat.GetCounters())
{
interestingToInspect.AppendLine(interestingCategory + ":" + counter.CounterName);
}
}
toInspect = interestingToInspect.ToString();
But could not find anything that seems to match. Is it not possible to observe these values from within the CLR or am I doing something wrong.
The environment, should it matter, is .NET 4.0 running on a 64-bit windows 7 box.
C is an imperative procedural language supporting structured programming, lexical variable scope, and recursion, with a static type system. It was designed to be compiled to provide low-level access to memory and language constructs that map efficiently to machine instructions, all with minimal runtime support.
In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.
Compared to other languages—like Java, PHP, or C#—C is a relatively simple language to learn for anyone just starting to learn computer programming because of its limited number of keywords.
In C programming language, %d and %i are format specifiers as where %d specifies the type of variable as decimal and %i specifies the type as integer. In usage terms, there is no difference in printf() function output while printing a number using %d or %i but using scanf the difference occurs.
You need to run the program as Administrator to access .NET CLR Memory category.
Try this simple test, using powershell:
When running as Administrator
[Diagnostics.PerformanceCounterCategory]::Exists(".NET CLR Memory")
True
When running without administrative privileges:
[Diagnostics.PerformanceCounterCategory]::Exists(".NET CLR Memory")
False
It should work. Note that as others have already set, the CLR counters are per instance counters, thus you need to specify the instance name for the process you wish to query the counters for.
So the statement you specified at the top of your post should work. However, you should also use the constructor overload that allows you to specify that you wish to access the instance in "read-only" mode:
new PerformanceCounter(".NET CLR Memory", "# bytes in all heaps", Process.GetCurrentProcess().ProcessName, true);
The second code fragment you posted does not work, as you didn't specify an instance name to the GetCounters()
operation. Use the GetCounters(string instanceName)
overload instead and it should work.
Finally, note that the instance name is not necessarily the same as Process.ProcessName
(or Process.GetCurrentProcess().ProcessName
for that matter). If there are multiple instances of a process, i.e. executable, the process name is created by appending a #<number>
. To figure out the actual instance name of a process you should query the .NET CLR Memory\Process ID
counter.
Example:
public static string GetInstanceNameForProcessId(int pid)
{
var cat = new PerformanceCounterCategory(".NET CLR Memory");
foreach (var instanceName in cat.GetInstanceNames())
{
try
{
using (var pcPid = new PerformanceCounter(cat.CategoryName, "Process ID", instanceName))
{
if ((int)pcPid.NextValue() == pid)
{
return instanceName;
}
}
}
catch (InvalidOperationException)
{
// This may happen, if the PC-instance no longer exists between the
// time we called GetInstanceNames() and the time we come around actually
// try and use the instance.
// In this situation that is not an error, so ignore it.
}
}
throw new ArgumentException(
string.Format("No performance counter instance found for process id '{0}'", pid),
"pid");
}
The instance name you gather by this method is good for performance counters in other ".NET CLR" categories as well.
Update: Added mitigation for potential race condition between the time we gather the potential instance names and the time we peruse them. A .NET process (for which we've seen an instance name) might no longer be there (and such the instance is also gone) when we try to use it.
Counters are per instance. Try adding:
foreach (var instance in cat.GetInstanceNames())
{
foreach (PerformanceCounter counter in cat.GetCounters(instance))
{
interestingToInspect.AppendLine(interestingCategory + ":" + counter.CounterName);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With