by Marcin Policht
Performance statistics are typically
retrieved using the Windows 2000 System Monitor. However, if you want to automate
the data collection process, you also have the option of using Windows Management
Instrumentation (WMI).
WMI is one of the technologies integrated by Microsoft
in Windows 2000 (and the upcoming XP and .NET). It offers a powerful set of system
management features, available through scripting API. WMI accesses managed
environments by employing COM objects called providers. Each provider is
responsible for handling communication between WMI and data generated by a
software or hardware component.
In the case of performance monitoring,
this data is generated by performance libraries according to settings stored in
the registry. These registry values are also read during AutoDiscovery/AutoPurge
(ADAP) processes which take place every time the WMI service starts.
Performance statistics are typically retrieved using the Windows 2000 System Monitor. However, if you want to automate the data collection process, you also have the option of using Windows Management Instrumentation (WMI). In the first of two articles on WMI, Marcin Policht describes in detail interaction with the WMI Performance Counter Provider.
WMI uses this
information to populate its internal database, called the repository, with the list
of counter objects registered with the system. The repository is arranged in a
complex hierarchy of inter-related classes (some of them linked by parent-child
relationships).
Performance related classes can be found by enumerating
children of the Win32_PerfRawData class. Here is a short script
GetPerfClasses.vbs, which accomplishes this task:
'*********************************************
'*** assign values to
variables
strClass = "Win32_PerfRawData"
strNamespace = "root/cimv2"
strComputer = WScript.Arguments(0)
'*********************************************
'*** connect to WMI
using moniker and retrieve collection of
'*** all subclasses of
Win32_PerfRawData
Set colSubClasses =
GetObject("winmgmts:{impersonationLevel=impersonate}//" & _
strComputer & "/" & strNameSpace).SubclassesOf(strClass)
'*********************************************
'*** enumerate all of
the Subclasses in the For loop
For Each objSubClass In colSubClasses
WScript.Echo objSubClass.Path_.Class
Next
In order to list
performance classes on the TARGET-SYSTEM computer, you would run:
cscript //nologo GetPerfClasses.vbs TARGET-SYSTEM
The results
would resemble the following list:
Win32_PerfRawData_ContentFilter_IndexingServiceFilter
Win32_PerfRawData_ContentIndex_IndexingService
Win32_PerfRawData_IAS_IASAuthenticationServer
Win32_PerfRawData_IAS_IASAuthenticationClients
Win32_PerfRawData_IAS_IASAccountingServer
Win32_PerfRawData_IAS_IASAccountingClients
Win32_PerfRawData_ISAPISearch_HttpIndexingService
Win32_PerfRawData_MSDTC_DistributedTransactionCoordinator
Win32_PerfRawData_PerfDisk_PhysicalDisk
Win32_PerfRawData_PerfNet_Server
Win32_PerfRawData_PerfNet_ServerWorkQueues
Win32_PerfRawData_PerfNet_Redirector
Win32_PerfRawData_PerfNet_Browser
Win32_PerfRawData_PerfOS_Cache
Win32_PerfRawData_PerfOS_Processor
Win32_PerfRawData_PerfOS_Memory
Win32_PerfRawData_PerfOS_Objects
Win32_PerfRawData_PerfOS_PagingFile
Win32_PerfRawData_PerfOS_System
Win32_PerfRawData_PerfProc_Process
Win32_PerfRawData_PerfProc_Thread
Win32_PerfRawData_PerfProc_JobObject
Win32_PerfRawData_PerfProc_JobObjectDetails
Win32_PerfRawData_PerfProc_ProcessAddressSpace_Costly
Win32_PerfRawData_PerfProc_Image_Costly
Win32_PerfRawData_PerfProc_FullImage_Costly
Win32_PerfRawData_PerfProc_ThreadDetails_Costly
Win32_PerfRawData_RemoteAccess_RASPort
Win32_PerfRawData_RemoteAccess_RASTotal
Win32_PerfRawData_RSVP_ACSPerRSVPService
Win32_PerfRawData_Spooler_PrintQueue
Win32_PerfRawData_TapiSrv_Telephony
Win32_PerfRawData_Tcpip_NBTConnection
Win32_PerfRawData_Tcpip_NetworkInterface
Win32_PerfRawData_Tcpip_IP
Win32_PerfRawData_Tcpip_ICMP
Win32_PerfRawData_Tcpip_TCP
Win32_PerfRawData_Tcpip_UDP
The naming reflects the fact that data
accessible via these classes is presented in a raw format (which might require
additional calculations). Class names also clearly indicate the types of objects
they represent (for example Win32_PerfRawData_PerfOS_Processor corresponds to
Processor object visible in System Monitor, Win32_PerfRawData_PerfOS_Memory is
equivalent to Memory object, etc).
A class can have one or more instance, depending on the number of instances of performance objects (e.g. 2 instances of the Win32_PerfRawData_PerfOS_Processor class on a dual CPU system). Each class also has
a set of properties, with names matching the names of object counters in System
Monitor. Besides its data type, each property, in turn, also has a set of
additional characteristics, specified by qualifiers. One of them, called
CounterType, determines what type of additional calculations might be necessary
to translate the raw property value into the form appearing in the System Monitor.
Performance Counter Provider
Windows 2000 supports two types of WMI providers, which allow access to
performance data:
– Performance Counter Provider
– Performance Monitor
Provider
This article will describe interaction with Performance
Counter Provider (the Performance Monitor Provider will be covered in my next
article). Performance Counter Provider is installed by default in Windows 2000,
so it’s readily available (unlike the Performance Monitor Provider, which has to
be properly registered). However, the data available through this provider
appears in “raw” (non-calculated) format.
As described before, the CounterType
qualifier for each property of an appropriate Win32_PerfRawData WMI class can be
used to determine how to derive useful information. CounterType is a numeric
value, which is described by CookingType string. You can find references to each
of the CookingType strings in the Windows 2000 Resource Kit. Here is the list of
CounterType values and corresponding CookingType strings, as specified in
the Microsoft Platform Software Development Kit:
CounterType Value CounterType
String
0 PERF_COUNTER_RAWCOUNT_HEX
256 PERF_COUNTER_LARGE_RAWCOUNT_HEX
2816 PERF_COUNTER_TEXT
65536 PERF_COUNTER_RAWCOUNT
65792
PERF_COUNTER_LARGE_RAWCOUNT
73728 PERF_DOUBLE_RAW
4195328
PERF_COUNTER_DELTA
4195584 PERF_COUNTER_LARGE_DELTA
4260864
PERF_SAMPLE_COUNTER
4523008 PERF_COUNTER_QUEUELEN_TYPE
4523264
PERF_COUNTER_LARGE_QUEUELEN_TYPE
5571840 PERF_COUNTER_100NS_QUEUELEN_TYPE
6620416 PERF_COUNTER_OBJ_TIME_QUEUELEN_TYPE
272696320
PERF_COUNTER_COUNTER
272696576 PERF_COUNTER_BULK_COUNT
537003008
PERF_RAW_FRACTION
541132032 PERF_COUNTER_TIMER
541525248
PERF_PRECISION_SYSTEM_TIMER
542180608 PERF_100NSEC_TIMER
542573824
PERF_PRECISION_100NS_TIMER
543229184 PERF_OBJ_TIME_TIMER
543622400
PERF_PRECISION_OBJECT_TIMER
549585920 PERF_SAMPLE_FRACTION
557909248
PERF_COUNTER_TIMER_INV
558957824 PERF_100NSEC_TIMER_INV
574686464
PERF_COUNTER_MULTI_TIMER
575735040 PERF_100NSEC_MULTI_TIMER
591463680
PERF_COUNTER_MULTI_TIMER_INV
592512256 PERF_100NSEC_MULTI_TIMER_INV
805438464 PERF_AVERAGE_TIMER
807666944 PERF_ELAPSED_TIME
1073742336
PERF_COUNTER_NODATA
1073874176 PERF_AVERAGE_BULK
1073939457
PERF_SAMPLE_BASE
1073939458 PERF_AVERAGE_BASE
1073939459 PERF_RAW_BASE
1073939712 PERF_PRECISION_TIMESTAMP
1073939715 PERF_LARGE_RAW_BASE
1107494144 PERF_COUNTER_MULTI_BASE
2147483648
PERF_COUNTER_HISTOGRAM_TYPE
You can collect the performance
data by querying values of instances of Win32_PerfRawData subclasses with the
following script:
'*********************************************
'*** ignore run-time errors
On Error Resume Next
'*********************************************
'*** assign values to
variables
strClass= WScript.Arguments(0)
strNamespace = "root/cimv2"
strComputer = WScript.Arguments(1)
'*********************************************
'*** connect to WMI
using moniker and retrieve collection of
'*** all instances of class
specified as the script argument
Set colInstances =
GetObject("winmgmts:{impersonationLevel=impersonate}//" & _
strComputer & "/" & strNameSpace).InstancesOf(strClass)
'*********************************************
'*** enumerate values
and CounterType qualifier for each
'*** property of each instance of the
specified class
For Each objInstance In colInstances
For Each objProperty In
objInstance.Properties_
WScript.Echo
objProperty.Name & Chr(9) & _
objProperty.Value & Chr(9) & objProperty.Qualifiers_.Item("countertype")
Next
Next
If you save this script as GetPerfCounters.vbs, by running
the following:
cscript //nologo GetPerfCounters.vbs
Win32_PerfRawData_PerfOS_Memory TARGET-SYSTEM
you would generate the listing
containing properties, their current values, and CounterType qualifier values
of an instance of Win32_PerfRawData_PerfOS_Memory class on the TARGET_SYSTEM computer.
Here is a sample listing:
Property Name Property Value
CounterType Value
AvailableBytes 27213824 65792
AvailableKBytes 26576
65792
AvailableMBytes 25 65792
CacheBytes 32694272 65792
CacheBytesPeak 32866304 65792
CacheFaultsPersec 138566 272696320
CommitLimit 318345216 65792
CommittedBytes 96124928 65792
DemandZeroFaultsPersec 146738 272696320
FreeSystemPageTableEntries
194787 65536
PageFaultsPersec 262541 272696320
PageReadsPersec 21992
272696320
PagesInputPersec 41788 272696320
PagesOutputPersec 2816
272696320
PagesPersec 44604 272696320
PageWritesPersec 176 272696320
PercentCommittedBytesInUse 23468 537003008
PercentCommittedBytesInUse_Base 77721 1073939459
PoolNonpagedAllocs
14326 65536
PoolNonpagedBytes 3489792 65792
PoolPagedAllocs 23324 65536
PoolPagedBytes 21929984 65792
PoolPagedResidentBytes 21753856 65792
SystemCacheResidentBytes 7221248 65792
SystemCodeResidentBytes 3428352
65792
SystemCodeTotalBytes 774144 65792
SystemDriverResidentBytes 290816
65792
SystemDriverTotalBytes 1966080 65792
TransitionFaultsPersec 86606
272696320
WriteCopiesPersec 5083 272696320
Note that the names
of counters correspond to the ones presented in the System Monitor. Their
values are meaningful in some cases (such as AvailableBytes, listing total number
of Available Bytes), while in others they don’t seem to make any sense. Such values need to
be recalculated according to a formula dependent on the counter type. Here is an
example: PagesPersec has the CounterType qualifier equal to 272696320, which
corresponds to PERF_COUNTER_COUNTER Counter Type string. According to the
description in the Windows 2000 Resource Kit, the formula for calculating the
actual value of the Pages/Sec counter of Memory object is:
(N1 –
N0)/((D1 – D0)/F)
where (N1 – N0) is the number of operations during
monitoring interval and (D1 – D0) is a number of processor ticks during this
interval. F represents frequency of the ticks. Ticks are basic units of
measuring length of time during which a thread can execute. Each thread is
assigned a quantum, which is a multiple of clock intervals. Value of a tick is
hardware dependent (you can measure it using a tool from www.sysinternals.com
called CLOCKRES.EXE) and is typically in a range of 10 – 15 ms.
If you
set the value of interval high enough, you might get approximate results by
measuring time interval in seconds, rather than in ticks. For example, the
following script compares the number of pages per second during arbitrarily set
time intervals. The script captures values of the monitored counter at the
beginning (value N0) and the end of the interval (value N1). The difference
between N1 and N0 is divided by number of seconds in the interval. This
procedure is repeated in the infinite loop – if you decide to end the script,
press Ctrl+C at the Command Prompt window from which you launched it.
'*********************************************
'*** assign values to
variables
strClass = "Win32_PerfRawData_PerfOS_Memory"
strNamespace =
"root/cimv2"
strProperty = "PagesPersec"
intInterval =
WScript.Arguments(0) 'interval (in seconds)
strComputer =
WScript.Arguments(1) 'target computer name
'*********************************************
'*** connect to WMI
using moniker and retrieve collection of
'*** all instances of class
specified as the script argument
Set colInstances =
GetObject("winmgmts:{impersonationLevel=impersonate}//" &
_
strComputer
& "/" & strNameSpace).InstancesOf(strClass)
'*********************************************
'*** capture the initial
value of the Counter you want to monitor
For Each objInstance In
colInstances
intN0 = objInstance.Properties_.Item(strProperty)
WScript.Echo intN0 Next
'*********************************************
'*** destroy the objects and collections you created
Set objInstance =
Nothing
Set colInstances = Nothing
'*********************************************
'*** in the infinite
loop, capture the Counter value at
'*** the end of the interval
While
True
'*********************************************
'*** go to sleep for intInverval
seconds
WScript.Sleep(intInterval
* 1000)
'*********************************************
'*** connect to WMI using moniker
and retrieve collection of
'***
all instances of class specified as the script argument
Set colInstances =
GetObject("winmgmts:{impersonationLevel=impersonate}//" & _
strComputer & "/" & strNameSpace).InstancesOf(strClass)
'*********************************************
'***
capture the final value of the Counter you want to monitor
For Each objInstance In
colInstances
intN1 = objInstance.Properties_.Item(strProperty)
WScript.Echo intN1
Next
'*********************************************
'*** display the
result
WScript.Echo
strProperty & Chr(9) & (intN1 - intN0)/(intInterval)
'*********************************************
'*** get ready for the next loop
Set objInstance = Nothing
Set colInstances = Nothing
intN0 = intN1
Wend
If
you save this script as GetCounter.vbs, in order to monitor the counter in 5
second intervals on a TARGET-SYSTEM computer, you would run:
cscript
//nologo GetCounter.vbs 5 TARGET-SYSTEM
As you can see, the process of
collecting performance data with WMI is fairly complex. Using Performance
Monitor Provider simplifies this slightly. I will describe the procedure for
implementing it in my next article. Fortunately, Windows XP offers considerable
improvements in Performance Monitoring capabilities by introducing new
providers, presenting calculated data directly.
In case you want to learn more about WMI (including how to
manage Windows processes, services, even logs, scheduled tasks, Windows
Installer applications, etc.) check out my recently released book:
WMI Essentials for Automating Windows Management
This article was originally published on Jul 18, 2001
1 of
1