Microsoft & .NET.NETReading and Publishing Performance Counters in .NET

Reading and Publishing Performance Counters in .NET

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Windows uses performance counters to collect and present performance data
from running processes. Windows itself provides hundreds of performance
counters, each monitoring a specific aspect of your system, from CPU utilization
to network traffic. In addition, other applications such as SQL Server or
Exchange publish their own custom performance counters that integrate into the
Windows performance monitoring system.

Performance counters are grouped into categories such as Memory, Processor
and PhysicalDisk. Each category contains one or more performance counters. For
example, the Memory category includes such categories as Available Bytes, Cache
Bytes, and Committed Bytes. Some categories also support an intermediate level
of organization called an instance. For example, the Network Interface category
has one instance for each network interface in your computer. You can thus
decide which network card to monitor with this instance.

Windows provides the System Monitor application (shown in Figure 1) to let
you see performance counters in action. But if you’re working in .NET, you can
go much deeper than this by using the
System.Diagnostics.PerformanceCounter class. In
this article, I’ll show you how to monitor existing performance counters and how
to create your own performance counters.

Windows System Monitor in action

Reading Performance Data

Visual Studio .NET makes it supremely easy to read existing performance
counters in your application, thanks to Server Explorer. If you haven’t
discovered Server Explorer yet, it’s normally docked as a slide-out window on
the left hand side of the VS .NET workspace. When you slide it out, you’ll find
a treeview that lets you drill into all sorts of resources, as shown in Figure
2. As you can see, Performance Counters are one of the categories of resource
that you can find here.

Performance counters in Server Explorer

In this screenshot, Skyrocket is the name of my local computer, .NET CLR
Security is a performance counter category, Total Runtime Checks is a
performance counter, and _Global_ is a performance counter instance. You can
drag and drop a performance counter instance from Server Explorer to a .NET
Windows form. When you do this, Visual Studio .NET creates a performance counter
component on the form. This is a visual wrapper for an instance of the
PerformanceCounter class.

For a quick demonstration, I dragged a performance counter and a timer
control to a form, added some buttons and a listbox, and wrote a tiny bit of
code:


Private Sub btnShowCPU_Click(ByVal sender As System.Object, _
 ByVal e As System.EventArgs) Handles btnShowCPU.Click
    ' Toggle the state of the CPU performance
    ' counter display in the list box
    If btnShowCPU.Text = "Show CPU usage" Then
        btnShowCPU.Text = "Stop"
        Timer1.Enabled = True
    Else
        btnShowCPU.Text = "Show CPU usage"
        Timer1.Enabled = False
    End If
End Sub

Private Sub Timer1_Tick(ByVal sender As Object, _
 ByVal e As System.EventArgs) Handles Timer1.Tick
    ' Display a new performance counter value
    ' in the list box
    lbPerfData.Items.Add("CPU usage: " & pcCpuTime.NextValue() & "%")
End Sub

Figure 3 shows this form in action, collecting samples of CPU usage. As you
can see in the code, the samples are generated by calling the
NextValue() method of a PerformanceCounter object
named pcCpuTime.

Collecting performance data in .NET

Looking into the code that the Windows Forms Designer generated shows how
easy it is to set up a PerformanceCounter for an existing
performance counter:


Friend WithEvents pcCpuTime As System.Diagnostics.PerformanceCounter

Me.pcCpuTime.CategoryName = "Processor"
Me.pcCpuTime.CounterName = "% Processor Time"
Me.pcCpuTime.InstanceName = "_Total"
Me.pcCpuTime.MachineName = "skyrocket"

After you set the CategoryName, CounterName,
InstanceName, and MachineName properties, you can read
a sample of the performance counter any time that you like. The
NextValue method will return the system’s calculated value for the
performance counter. There’s also a NextSample method which returns
a point-in-time sample; this may differ from the calculated value for counters
which require multiple samples (for example, those that return a bytes per
second rate).

Creating Your Own Performance Counter

Creating your own performance counters uses several classes, all in the
System.Diagnostics namespace. Here’s an example that creates two
performance counters:


Private Sub btnRegisterCustom_Click(ByVal sender As System.Object, _
 ByVal e As System.EventArgs) Handles btnRegisterCustom.Click
    ' Create a custom performance counter
    If Not PerformanceCounterCategory.Exists("Developer.com") Then
        Dim ccd1 As New CounterCreationData
        ccd1.CounterName = "RandomCounter"
        ccd1.CounterType = PerformanceCounterType.NumberOfItems32

        Dim ccd2 As New CounterCreationData
        ccd2.CounterName = "IncreasingCounter"
        ccd2.CounterType = PerformanceCounterType.NumberOfItems32

        Dim ccds As New CounterCreationDataCollection
        ccds.Add(ccd1)
        ccds.Add(ccd2)

        PerformanceCounterCategory.Create("Developer.com", _
         "Developer.com counters", ccds)

        btnShowCustom.Enabled = True
    End If
End Sub

The CounterCreationData class contains the information necessary
to create a single counter: its name and its type. Instances of this calss can
be collected into an instance of the CounterCreationDataCollection
class. That collection, in turn, can be passed to the
PerformanceCounterCategory.Create method to create both the
category and the counters. Note that .NET doesn’t let you add new performance
counters to an existing category.

After running this code, you’ll find the new category and the new counters
exposed in the Server Explorer tree. You can drag them to the form and work with
them just like any other performance counter. However, as things stand, the
counters won’t have any value. They’re waiting for you to create one.

Supplying Values for Performance Counters

There isn’t any great trick to supplying your own values for performance
counters that you create (note that you can’t supply a value for any of the
system counters). Here’s a bit of code to both modify and display the custom
performance counters that I just created:


Private Sub btnShowCustom_Click(ByVal sender As System.Object, _
 ByVal e As System.EventArgs) Handles btnShowCustom.Click
    ' Turn on the custom counter display
    Timer2.Enabled = True
End Sub

Private Sub Timer2_Tick(ByVal sender As System.Object, _
 ByVal e As System.EventArgs) Handles Timer2.Tick
    ' Update and display the custom counters

    ' First, get the counters
    Dim pcRandomCounter As PerformanceCounter = _
     New PerformanceCounter("Developer.com", "RandomCounter", False)
    Dim pcIncreasingCounter As PerformanceCounter = _
     New PerformanceCounter("Developer.com", "IncreasingCounter", False)

    ' Now adjust their values
    pcRandomCounter.RawValue = Int(Rnd(1) * 50000)
    pcIncreasingCounter.Increment()

    ' Display in the list box
    lbPerfData.Items.Add("Random Counter: " & _
     pcRandomCounter.NextValue())
    lbPerfData.Items.Add("Increasing Counter: " & _
     pcIncreasingCounter.NextValue())

End Sub

The trick here is in the constructor for the PerformanceCounter
class. The three arguments to this particular form of the constructor are the
category name, the counter name, and a boolean that indicates whether the
counter should be opened read-only. Supplying False for this
boolean indicates that I want a read-write counter. After that, the code can
just set the RawValue property of the counter, or it can call the
Increment or Decrement methods to adjust the value by
1 unit at a time. Figure 4 shows this code in action.

Setting and reading custom counters

Another Bit of Fit and Finish

I hope you’ll agree that working with performance counters in .NET is pretty
simple. The next step is to integrate counters into your own applications. While
most applications won’t need to display the system counters, it can be very
helpful to your users to create your own custom counters. For example, suppose
you’re working on an application to process incoming Web requests for a
particular set of files. Would it be helpful to administrators to have counters
howing how many requests were successful and how many failed? You bet! And it
will only take you a few lines of code to build them.

Mike Gunderloy is the author of over 20 books and numerous articles on
development topics, and the lead developer for Larkware. Check out his latest book, Coder to Developer from Sybex. When
he’s not writing code, Mike putters in the garden on his farm in eastern
Washington state.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories