Time Based Operations
The lifecycle for these counters is pretty straightforward:
- System Preparation: creation of counters in the Windows OS.
- Library Initialization: loading and initializing the library inside your running program
- Counter caching an optional step that warms up the counter library
- Key retrieval for any counter you use
- Counter usage including the API
You must create any custom counters as Administrator before running any program that uses the Performance Counter system. The simplest way to do this is in a Powershell script because Powershell is available on all modern Windows operating systems. The following sample script creates a new Category "Freemansoft.JavaTestCategory" and two simple counters "TestCounter" and "TestRate".
Some counters work in pairs with a primary counter and a base counter. You must create paired counters together in the same Powershell script. Windows assumes that compound counters are always created with the primary first and the base immediately following.
You must load the counter library one time somewhere in your program setup and initialization. The library uses Java JNI to load a DLL. Each DLL can only be loaded once. Here is code from one of the Java examples.
Category / Counter Caching
This library wraps a Windows API that proxies the Windows Performance Counter library. There is a large, about 400ms, penalty the first time you access a performance counter. You can remove this penalty for users by warming up the library by pre-caching the categories. There is a simple API for this using this method where you specify the full string name of the Category and the optional instance. You can pass null or empty string for a Category with only a default Instance.
The underlying C#/C library API accepts string based Category, Instance and Counter names for every operation. We get significantly better performance by creating an API that avoids string marshaling and copying wherever possible.
The WindowsPerformanceFacade class uses a unique integer based key to represent a Category, Instance, Counter combination. The Instance value is set to null in the case of a Category without multiple instances. Applications should retrieve and cache keys for any counters they intend to use in their start-up code.
The rest of the API manipulates counters. There are a couple subtleties to the API
There is no two value API for Decrement().
NextValue() returns the calculated value not the RawValue of the counter. See the Microsoft documentation for information on how calculations are made for various counters.
SetRawValue() and GetRawValue() get the current non-computed value for the counter. You may use SetRawValue() to initialize a counter. Both counters must be individually manipulated if you are using SetRawValue() There is no Counter/Base counter combination method at this time.
- Most of the manipulation methods have two overrides. One that takes a single value and the other takes two values.
- Always use the single for simple counters.
- You can use either the single or two value methods for compound counters where there is a primary counter and a base counter.
- The single value method will automatically increment any associated base counter by 1.
- The two value method lets you specify exactly the values you want for the primary and base counter.
Time Based Operations
Some counters use intrinsic time calculations. Counters like ops/second are simple counters that accept some integer as a count and then calculate the rate/second using the built in timing calculations.
Some compound counters use time in the numerator of a rate calculation, time/packet or time/byte. The caller provides time in these situations using the Microsoft Stopwatch timer and not the system timer. You cannot use Java Date or Time values when doing time operations in the Windows Performance Counters. The Stopwatch is a high resolution timer with more precision than the standard timer. The Stopwatch is exposed to Java applications via the GetStopwatchTimestamp() in both WindowsPerformanceFacade and WidnowsPerformanceLiason.
- Interval timers can be based on some "amount of time" that an operation took or paused. In this case, make a GetStopWatchTimestamp()call prior to the operation and then another at the end of the operation. Pass the difference in the two times to the timer.
- Other timers just take the current time as a value. In this case just call the GetStopWatchTimestamp()method and pass the results to the timer call.
Windows Performance Counters