views:

130

answers:

6

I've been asked how to find out how much memory and CPU my program is using, and I've been referred to Performance Counters. However, when I look at the documentation it starts off by telling me about providing consumer data by creating a manifest for my application, and my eyes glaze over. It's nice that such a general-purpose tool is there, I suppose, but all I wanted was a set of functions that would tell me how much memory and CPU my program is using.

Are performance counters the right tool for my job? If so, how do I use them? I really don't want to have to set up anything outside my C# application.

NOTE: I'm not looking for a third-party profiling app, I need to have the memory and CPU data displayed by my app.

UPDATE: I've removed time in functions, as it seemed to be confusing the matter.

+1  A: 

Performance counters will not tell you how much time your application spends in a function. For that you can use some kind of timer class which you start at the beginning of the function and stop at the end.

shoosh
Isn't it as simple as to add a DateTime start = DateTime.Now; and DateTime end = DateTime.Now; at the begining and end of the function? Or before and after it's run. Then just do TimeSpan timespent = end - start; and do some logging or something with the value.
Alxandr
@shoosh: OK, how about the rest of it?
Simon
@Alxandr: millisecond accuracy isn't enough, and getting a better resolution with Stopwatch takes so long that the values are skewed.
Simon
+3  A: 

You can use perfmon out of the box to monitor CPU, Memory and Disk usage as well as many .NET specific performance counters. perfmon comes with windows.

The eye-glazer is required only if you want to write your own perfmon, or if you want to offer your own performance counters. The latter would be interesting only if your users would need to monitor this value (e.g. you are developing a server application and your users need to make sure there are no more than 10% of connections rejected due to invalid moon phase).

For determining how much time you spend in certain functions, use a profiler.


The Performance Counter API would allow you to monitor the data together with existing performance counters (which might tell you e.g. that function Foo gets very slow every night after 11 because some other process is thrashing the disk), and the monitor can run as a service and produce log files for later analysis.

You must figure out whether these benefits are worth the additional trouble of performance counters, or if you are better off with a logging system.

There are quite some samples out there that might make it easier for you. However, it still pays to understand the architecture and "official" terminology. Typically, MS API's do require a lot of reading and looking for some good wrapper code, that doesn't mean they are always painful.

peterchen
I effectivedly do want to write my own perfmon, but only for my application. It needs to display its own CPU and memory use.
Simon
@Simon: I've updated the answer.
peterchen
Thanks - the SystemMonitor project in particular looks like a good lead.
Simon
A: 

how much time it is spending in function

For this you need a profiler (such as the one included in the more advanced editions of Visual Studio). This will give you details of how many times each method is called (with or without functions it calls).

Essential detail for identifying bottlenecks.

CPU

The total process CPU-seconds performance counters (or columns in Task Manager or Process Explorer) will give you this. In practice you might need more detail (kernel vs. user time) that is also available.

memory

This is the difficult part.... "memory" can mean: allocated virtual address space, committed virtual address space, working set, peak working set, private memory, ...

You probably need to spend some time with Windows internals or a similar reference to understand how these are different and what they mean before starting any real analysis.

Richard
How would I go about finding the "total process CPU-seconds performance counters"?
Simon
@Simon: Under process in perfmon.
Richard
@Richard: I mean, how would I use it from within my app?
Simon
@Simon `PerformanceCounter` class.
Richard
@Richard: Yes, I know - hence my question. But how would I use the PerformanceCounter class to get the total process CPU-seconds performance counter?
Simon
@Simon: Have you tried using the same name as is displayed in perfmon?
Jason D
@Simon: You need to iterate through the process id counters to find the name/id assigned for the process, then you can open the right CPU time counter. If you want the current process, `System.Diagnostics.Process.Current` will be easier, otherwise you have to do the hard work.
Richard
+2  A: 

Use WMI, this tool to help you about windows counters that may be useful WMI Code Creator.

More help with this example WMI Made Easy For C#

lsalamon
+1  A: 

Assuming a single instance application for CPU usage and Memory (Process Working Set) you could do something like the following:

public static void Main(string[] args)
{
    string processName = Process.GetCurrentProcess().ProcessName;
    int processorCount = Environment.ProcessorCount;

    // Simulate process usage
    for (int i = 0; i < processorCount * 2; i++)
    {
        var t = new Thread(() =>
            {
                while (true) { Console.WriteLine("Busy..."); }
            });

        t.IsBackground = true;
        t.Start();
    }

    var cpu = new PerformanceCounter("Process", "% Processor Time");
    cpu.InstanceName = processName;
    cpu.NextValue();

    var ram = new PerformanceCounter("Process", "Working Set");
    ram.InstanceName = processName;

    float memUsage = (ram.NextValue() / 1024) / 1024;
    Console.WriteLine("Memory Usage: {0}MB", memUsage);

    float cpuUsage = cpu.NextValue() / (float)processorCount;
    Console.WriteLine("CPU Usage: {0}%", cpuUsage);
}

For the CPU usage perf counter the first call to NextValue returns 0 so only the second call is used to display the value. The reported usage is the sum for all machine processors so the average is calculated before being displayed.

João Angelo
+1  A: 

For simple information, have a look at these values from within your C# code, then pick what's most relevant to you:

System.Diagnostics.Process.GetCurrentProcess().TotalProcessorTime
System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64
System.Diagnostics.Process.GetCurrentProcess().VirtualMemorySize64
System.GC.GetTotalMemory(false)

PrivateMemorySize is the total Private Bytes (managed and unmanaged combined) for your process. GetTotalMemory gives you the total managed memory usage for your app, passing true will force a GC before getting the value.

Niall Connaughton
Looks good - what about CPU?
Simon
I don't know if there is anything for the current, instantaneous CPU usage, but the TotalProcessorTime will give you how much time in total your Process has used. If what you're after is an instantaneous report of CPU usage, you'll have to look at Performance Counters or WMI.
Niall Connaughton