Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#: Accessing PerformanceCounters for the ".NET CLR Memory category"

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.

like image 870
Mads Ravn Avatar asked Jan 16 '11 13:01

Mads Ravn


People also ask

What do you mean by C?

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.

What is the full name of C?

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.

Is C language easy?

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.

What is %d in C programming?

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.


3 Answers

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

like image 56
Oleg D. Avatar answered Nov 15 '22 20:11

Oleg D.


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.

like image 20
Christian.K Avatar answered Nov 15 '22 20:11

Christian.K


Counters are per instance. Try adding:

foreach (var instance in cat.GetInstanceNames())
{
    foreach (PerformanceCounter counter in cat.GetCounters(instance))
    {
        interestingToInspect.AppendLine(interestingCategory + ":" + counter.CounterName); 
    } 
}
like image 37
jyoung Avatar answered Nov 15 '22 19:11

jyoung