Performance counters the basic unit of measurement for gauging the performance of your application were introduced in Chapter 12, when we considered connection pooling. However, a lot more information is available from the performance monitor than the number of open connections, and this information can prove tremendously useful when you're trying to improve an application's performance. Performance counters are particularly useful when you're attempting to identify a bottleneck that's hampering application performance. To open the Performance window, choose Performance from the Administrative Tools section in Control Panel. By default, you'll see only performance counters for measuring basic information such as the computer's CPU and disk drive use. However, .NET installs much more useful counters for tracking application performance. To add a new counter, right-click on the Counter list, choose Properties, and click on the Data tab. Before continuing, remove all the default counters. You can then click Add to insert some more useful ones (as shown in Figure 14-8). Note that you can specify a computer name in the Add Counters window. This enables you to monitor the performance of a remote computer without incurring additional overhead that could skew the results. Figure 14-8. Adding performance counters
Essential Performance CountersOn an average computer, dozens of performance counters are available. Examples include data source specific counters (such as those included with SQL Server), the ten basic .NET performance categories, two ASP.NET categories, and hardware-specific categories that profile memory or CPU usage and disk activity. Clearly, it's not easy to sort out which counters are best for profiling system activity. It can help to refer to the descriptions of some of the most important categories and counters in Table 14-6. You also can refer to the MSDN Help for a full description of every .NET counter.
You might have noticed one puzzling fact: There are four ASP.NET categories, and some of them seem similar. You'll find an ASP.NET category, which provides information about the overall performance of ASP.NET, and an ASP.NET Applications category, which provides information about a single specified Web application. You'll also find two extremely similar categories with version information (ASP.NET [version] and ASP.NET Apps [version]). These categories are actually the same as the versionless categories. Technically, the versionless categories map to the latest version of the .NET Framework. If you install multiple versions of the .NET Framework, you will find one ASP.NET [version] category and one ASP.NET Apps [version] category for each version of the framework. However, the ASP.NET and ASP.NET Application categories automatically represent the latest installed version.
Custom Performance Counters.NET provides classes in the System.Diagnostics method that enable you to interact programmatically with Windows performance counters, retrieving the current set of counters, retrieving the current value for a specific counter, or creating and incrementing your own counters. This section examines these tasks. The first step when you use custom counters is to create the counters and counter category. You can do this manually in Visual Studio .NET using Server Explorer or programmatically using the classes in the System.Diagnostics namespace. You can even create a custom installer as part of a Visual Studio .NET setup project, which adds the counters when the application is installed on a computer. Listing 14-13 shows the code needed to create a custom counter category (provided it doesn't already exist) and add two counters. Listing 14-13 Creating custom countersIf Not (PerformanceCounterCategory.Exists("Shopping Counters")) Then Dim Counters As New CounterCreationDataCollection() ' Create a simple counter that records a total value. Dim CountCounter As New CounterCreationData() CountCounter.CounterName = "Total Purchases" CountCounter.CounterHelp = "Total number of purchases " & _ "submitted by this component" CountCounter.CounterType = PerformanceCounterType.NumberOfItems32 ' Create a rate counter that records a per second value. Dim RateCounter As New CounterCreationData() RateCounter.CounterName = "Purchases/Second" RateCounter.CounterHelp = "Current number of purchases per " & _ "second submitted by this component" RateCounter.CounterType = RateOfCountsPerSecond32 ' Add both counters to the collection. Counters.Add(CountCounter) Counters.Add(RateCounter) ' Create the custom category. PerformanceCounterCategory.Create("Shopping Counters", _ "Counters for the Shopping.dll component", Counters) End If The CounterType property identifies the type of counter that you're creating. Although .NET provides several options, most choices are concurrency counters and rate counters. Concurrency counters reflect a simple value. When your program increments a concurrency counter, the new value appears identically in the performance monitor. Rate counters involve an extra calculation. You set rate counters in the same way that you set concurrency counters. Behind the scenes, however, these values are cached for a second. The current value of the counter is always equal to the total count received in the last second. The 32 at the end of the counter type indicates the size allocated to store the counter data. If you expect to require values larger than a 32-bit integer, you can use the corresponding type that ends with 64. You also can use more advanced counters such as AverageCount64 or CounterDelta32, which calculate values by comparing the number of counts in a given interval with the number of counts in a previous interval. The formulas used for these calculations are outlined in the MSDN Reference. When you create counters, it's also a good idea to include some descriptive information. In Listing 14-13, this includes the CounterHelp string assigned to each counter and a similar category description. The user can view this information when adding a counter in the Performance window (as shown in Figure 14-9). Figure 14-9. Adding custom performance counters
As you might imagine, .NET makes it similarly easy to remove a counter category: PerformanceCounterCategory.Delete("Shopping Counters") If you prefer to create counters at design time with Visual Studio .NET, you can just follow these steps:
To use a counter, you need to create a counter instance. Counter instances relate to performance counters in the same way that objects relate to classes. Although there is only one Purchases/Second counter defined, a server component can create multiple instances. Depending on your needs, a counter might be created for every instance of a server-side component, or a single server-side component might create multiple instances to represent work it is doing for different clients. Creating a performance counter is easy. You just create an instance of the PerformanceCounter class and specify the counter category, counter name, and the instance name. You must also add the optional False parameter; otherwise, the counter will be created in read-only mode. (You also can access a counter on another computer by specifying a machine name parameter, but only in read-only mode.) For example, here's the code that creates an instance of the total counter and increments it by one: Dim TotalCounter As New PerformanceCounter("Shopping Counters", _ "Total Purchases", "NewCustomerInstance", False) ' Increment the counter by 1. TotalCounter.Increment() You also can set the PerformanceCounter.RawValue property directly, but the Increment method ensures that the operation is atomic. This way, multiple threads or components can increment the same counter at once without losing data. Figure 14-10 shows the result in the Performance window after the total counter has been incremented several times. Figure 14-10. Incrementing a custom concurrency counter
You can adjust the rate counter just as easily. If you monitor the performance counter while executing the following code, however, a very different behavior results: The counter spikes to 100 once the code is executed, but falls back rapidly, reaching 0 one second later, as the rate of counts/second dwindles. Dim RateCounter As New PerformanceCounter("Shopping Counters", _ "Purchases/Second", "NewCustomerInstance", False) ' Increment the counter by 100. RateCounter.IncrementBy(100) Figure 14-11 shows the results of executing this code multiple times. Figure 14-11. Incrementing a custom rate counter
When the application ends or when the counters are no longer needed, be sure to release them. Otherwise, the counters remain until the Performance window is closed. RateCounter.RemoveInstance() TotalCounter.RemoveInstance()
|