Performance Counters

Chapter 11 - Performance
byJohn Kauffman, Fabio Claudio Ferracchiatiet al.?
Wrox Press ?2002

Since the earliest days of Windows NT, the Windows operating system has provided performance counters as a means by which to view certain categories of performance-related information. The values of these counters can be viewed administratively using the PerfMon utility, but programmatic access has taken some effort - at first, they were only available by parsing complex data structures retrieved from the Windows registry, or by using a DLL that only shipped with the Windows SDK. In .NET, however, performance counters are laid bare to all developers through the classes of the System.Diagnostics namespace, which include PerformanceCounterManager, PerformanceCounterCategory, and PerformanceCounter.

Since performance counters originated on Windows NT, they are not supported on Windows 98 and Windows ME. Windows NT, 2000, and XP do support performance counters.

The complete set of performance counters is broken down into categories, and since each category is exposed as a performance counter object, the two terms "object" and "category" will get used interchangeably in this discussion. For ASP.NET, performance counters can be broken down into the following categories:

  • ASP.NET Application. This category includes a variety of counters that can be used to gauge the performance of an ASP.NET application. Such counters include (but certainly are not limited to) Cache Total Hits, Cache Total Misses, Cache Total Hit Ratio, Sessions Active, and Sessions Timed Out. For the most part, the name of each counter is self-documenting. Exhibiting similarly self-documenting behavior are the ASP.NET application performance counters that can be used to determine database performance. Counters in this genre include Transactions Aborted, Transactions Committed, Transactions Pending, Transactions Total, and Transactions/Sec.

  • ASP.NET System. This category's performance counters do not apply to a single ASP.NET application, but instead represent the state of all ASP.NET applications presently executing on a given web server. These counters include Application Running, Requests Queued, Request Wait Time, and State Server Session Active.

The .NET Framework also exposes a variety of different categories of counters that deal with aspects such as memory, networking, remoting, and security. More relevant to the present subject, however, is the .NET CLR Data category, which includes counters that demonstrate various performance aspects of the SQL Server .NET data provider. These counters can provide insight into a particular application that uses this data provider, or all the applications that use it. The specific counters within this category are:

  • Current # connection pools - the total number of current connection pools for a specific instance. We've already discussed how connection string attributes can affect connection pools, and this particular counter is indispensable in tracking down issues related to inadvertently creating additional ones.

  • Current # pooled and nonpooled connections - the total number of database connections presently open. This counter provides a quick way to check whether an application has circumvented the default behavior, which is to use connection pooling.

  • Current # pooled connections - the total number of database connections that are presently open and associated with a connection pool.

  • Peak # pooled connections - the maximum number of connections open during peak execution. Recall that the Max Pool Size connection attribute can be used by a connection string to increase the upper bound on the number of connections maintained in a given pool. Knowing the peak number of pooled connections should influence the value you associate with the Max Pool Size connection attribute.

  • Total # failed commands - the total number of commands that have failed, regardless of the reason for the failure.

  • Total # failed connects - the total number of connections that have failed, regardless of the reason for the failure. Included in this total are connection attempts that timed out because the maximum number of connections in the pool was exceeded - but remember that the Max Pool Size connection attribute is just one possible cause of a failed connection. Another variable in the equation is the Connection Timeout connection attribute, which can be increased so that waiting connections do not time out as readily.

The true value of performance counters is that they can be accessed either using the PerfMon utility (Control Panel | Administrative Tools | Performance), or programmatically. It's even possible for developers to create their own performance counter objects in order to provide data that's exactly right for their own specific application, but this topic is beyond the scope of this chapter.

An example of the PerfMon tool being used to monitor .NET data performance counters is shown below:

click to expand

An Add counter icon (+) is provided on PerfMon's toolbar. Clicking on this icon allows:

  • A machine (host) to be selected, so that the performance counters on that host can be accessed.

  • A performance counter object to be selected, such as the .NET CLR Data counter object.

  • A specific instance to be selected. You can choose to monitor one application, or use _global_ to specify all applications using the SQL Server .NET data provider.

  • A specific counter to be selected. The above screenshot shows selected counters such as Current # connection pools and Current # pooled and nonpooled connections.

When you're using a large number of performance counters, the PerfMon utility provides a useful graphical display in the area beneath the toolbar containing the Add icon. Underneath this graphical display, data is presented that pertains to the counter currently highlighted. In the previous screenshot, they deal with the Current # connection pools counter. The values displayed include the Last value for this counter, the Average number for this counter, the Minimum number for this counter, the Maximum number for this counter, and the length of time over which performance was measured (Duration).

Programmatic Performance Counter Access

As mentioned above, the System.Diagnostics namespace provides a variety of classes that can be used to access performance objects and performance counters. These classes include:

  • PerformanceCounterCategory, which is used to retrieve performance objects and their counters

  • PerformanceCounter, which is used to access information (name, value, help string, etc.) from a specific performance counter

The PerformanceCounterCategory class exposes a shared method called GetCategories() that retrieves the name of all the performance counter objects for the present host, or a specific remote host. Once an instance of the PerformanceCounterCategory class has been created for a given performance counter category (such as .NET CLR Data), information specific to this category can be retrieved. For example, the GetInstanceNames() method can be called to retrieve the names of applications with a current interest in this category, and GetCounters() can be used to retrieve the counters associated with the category. The GetCounters() method returns an array of type PerformanceCounter.

The PerformanceCounter class exposes properties and methods that can be used to access a performance counters value, and to manipulate that value. Among these is the NextValue() method, which retrieves the 'next' value (the method is designed to be called iteratively) as a Float. In the world of connection pools, however, there are no decimal values (you can't have half a connection), so we'll safely be able to cast it to an Integer.PerformanceCounter also implements properties that allow the counter's name (CounterName), type (CounterType), and help information (CounterHelp) properties to be queried.

The WXPerfCount application, which you can download from www.wrox.com, makes use of the PerformanceCounter class in order to display information about the counters associated with the .NET CLR Data performance counter object. The basic premise of the application is to create a slew of connection pools, connections, failed connection attempts, and failed commands. Once this is done, the .NET CLR Data performance counters are retrieved and displayed.

Without getting into detail, the WXPerfCount application creates each PerformanceCounter object by passing the category name and application instance that the counter is associated with to the object's constructor. Also passed to the constructor is the performance counter's category name. Once the performance counter instance is created, its CounterName property and NextValue() method are used to display a string indicating the value associated with the performance counter.

Try It Out - Using Performance Counters to Evaluate Performance

start example
  1. Create a new Visual Basic ASP.NET Web Application project named WXPerfCount.

  2. Add some Label controls to WebForm1.aspx that will be used to display our performance counter results. The labels that should be added are LabelNumCPools, LabelTotalCons, LabelPooledCons, LabelPeakCons, LabelFailedCom, and LabelFailedCons. You'll end up with something like this:

    click to expand

  3. Moving on to the code-behind file, we know that we'll be using objects of the PerformanceCounter class that's located in the System.Diagnostics namespace. With that in mind, we need to add an Imports statement right at the top:

     Imports System.Diagnostics 

  4. Next, we add a function to the WebForm1 class that will retrieve the next value from a performance counter that's passed to it by name. The function returns the value of the counter formatted as a string, ready for display:

     ' Permissible values for counterName include: ' "SqlClient: Current # connection pools" ' "SqlClient: Current # pooled and nonpooled connections" ' "SqlClient: Current # pooled connections" ' "SqlClient: Peak # pooled connections" ' "SqlClient: Total # failed commands" ' "SqlClient: Total # failed connects" Function WXGetPerfCountValue(ByVal counterName As String) As String   Dim category As String = ".NET CLR Data"   Dim instance As String = "_global_"   Dim pc As PerformanceCounter = Nothing   pc = New PerformanceCounter(category, counterName, instance)   Return pc.NextValue().ToString() End Function 

  5. In order to give these controls something to display, we need to do some work with a database. First of all, add a Button called ButtonPerf to the form, and double-click on it to add a click event handler to the code-behind file.

  6. The version of this project that's available for download tests a number of different connection strings in order to provide values for all of our label controls; here, we'll substitute something a little simpler:

     Private Sub ButtonPerf_Click(ByVal sender As System.Object, _                       ByVal e As System.EventArgs) Handles ButtonPerf.Click   Dim count As Integer = 0   Dim tempConn As  SqlConnection   For count = 1 To 100     tempConn = New SqlConnection("server=localhost; database=northwind;" & _                                  "uid=sa; pwd=; Connection TimeOut=" & _                                  count.ToString())     tempConn.Open()   Next End Sub 

  7. To the same handler, add code that reads the performance counters and displays their values in the labels we created earlier:

     LabelNumCPools.Text = _   WXGetPerfCountValue("SqlClient: Current # connection pools") LabelTotalCons.Text = _   WXGetPerfCountValue("SqlClient: Current # pooled and nonpooled connections") LabelPooledCons.Text = _   WXGetPerfCountValue("SqlClient: Current # pooled connections") LabelPeakCons.Text = _   WXGetPerfCountValue("SqlClient: Peak # pooled connections") LabelFailedCons.Text = _   WXGetPerfCountValue("SqlClient: Total # failed commands") LabelFailedCons.Text = _   WXGetPerfCountValue("SqlClient: Total # failed connects") 

  8. If you run the code as presented in this book, you find yourself faced with output that looks something like the screenshot below. The longer sample that comes with the code download allows you finer control over the database connections that are created. As you can see, it's further confirmation that providing different timeout values results in the creation of separate connection pools.

    click to expand

end example

If you have problems running this example, the likely cause is a problem with your security settings - Windows won't allow users below a certain privilege level to use the facilities of the System.Diagnostics namespace. Should you run into difficulties, go to Control Panel | Users and Passwords, and change the group of the user called ASPNET to Administrators. Be aware that there is a security risk inherent in this operation, which you should only perform on a development machine.

In truth, although it's provided a demonstration of how to use performance counters programmatically, the code in the WXGetPerfCountValue() method is not the best way to use the PerformanceCounter class. More typically, instances of such counters are created and accessed repeatedly. By calling the NextValue() method of a performance counter repeatedly over a period of time, a histogram of performance information can be retrieved. When you're looking for erroneously created connection pools, or the peak number of connections, a histogram is a valuable tool for diagnosing the bottleneck.



Beginning ASP. NET 2.0 and Databases
Beginning ASP.NET 2.0 and Databases (Wrox Beginning Guides)
ISBN: 0471781347
EAN: 2147483647
Year: 2004
Pages: 263

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net