ID: Q107728
3.10 3.50 3.51 4.00 WINDOWS NT kbprg
The information in this article applies to:
The performance data begins with a structure of type PERF_DATA_BLOCK and is followed by PERF_DATA_BLOCK.NumObjectTypes data blocks. Each data block begins with a structure of type PERF_OBJECT_TYPE, followed by PERF_OBJECT_TYPE.NumCounters structures of type PERF_COUNTER_DEFINITION. Next, there are PERF_OBJECT_TYPE.NumInstances structures of type PERF_INSTANCE DEFINITION, each directly followed by an instance name, a structure of type PERF_COUNTER_BLOCK and PERF_OBJECT_TYPE.NumCounters counters. All of these data types are described in WINPERF.H.
The following steps are used to retrieve all of the counter information from the registry:
1. Allocate a buffer to obtain the performance data. For single objects,
you may need at little as 1.5K. For global objects, you may need as
much as 50K. Call RegQueryValueEx() to obtain the data. If the call
returns ERROR_MORE_DATA, then the buffer size was not big enough.
Increase the size of the buffer and try again. Repeat until the call
is successful.
2. Get the first object type in PerfObj.
3. Get the first instance.
4. Get the first counter and its data. At this point, if the object has no
instances, the next thing will be a pointer to a single
PERF_COUNTER_BLOCK; otherwise, the next thing will be a pointer to the
first PERF_INSTANCE_DEFINITION. Check PerfObj->NumInstances to find out
how many instances there are.
5. Get the next counter and its data. Repeat for all PerfObj->NumCounters
counters.
6. After all counters are retrieved for the instance, get the next
instance and all its counters. Repeat for all PerfObj->NumInstances
instances.
7. After all instances of the object type are retrieved, move to the next
object type and repeat steps 3 - 7.
#include <windows.h>
#include <stdio.h>
#include <malloc.h>
#define TOTALBYTES 8192
#define BYTEINCREMENT 1024
void main()
{
PPERF_DATA_BLOCK PerfData = NULL;
PPERF_OBJECT_TYPE PerfObj;
PPERF_INSTANCE_DEFINITION PerfInst;
PPERF_COUNTER_DEFINITION PerfCntr, CurCntr;
PPERF_COUNTER_BLOCK PtrToCntr;
DWORD BufferSize = TOTALBYTES;
DWORD i, j, k;
// Allocate the buffer.
PerfData = (PPERF_DATA_BLOCK) malloc( BufferSize );
while( RegQueryValueEx( HKEY_PERFORMANCE_DATA,
"Global",
NULL,
NULL,
(LPBYTE) PerfData,
&BufferSize ) == ERROR_MORE_DATA )
{
// Get a buffer that is big enough.
BufferSize += BYTEINCREMENT;
PerfData = (PPERF_DATA_BLOCK) realloc( PerfData, BufferSize );
}
// Get the first object type.
PerfObj = (PPERF_OBJECT_TYPE)((PBYTE)PerfData +
PerfData->HeaderLength);
// Process all objects.
for( i=0; i < PerfData->NumObjectTypes; i++ )
{
printf( "\nObject: %ld\n", PerfObj->ObjectNameTitleIndex );
// Get the counter block.
PerfCntr = (PPERF_COUNTER_DEFINITION) ((PBYTE)PerfObj +
PerfObj->HeaderLength);
if( PerfObj->NumInstances > 0 )
{
// Get the first instance.
PerfInst = (PPERF_INSTANCE_DEFINITION)((PBYTE)PerfObj +
PerfObj->DefinitionLength);
// Retrieve all instances.
for( k=0; k < PerfObj->NumInstances; k++ )
{
printf( "\n\tInstance: %S\n", (char *)((PBYTE)PerfInst +
PerfInst->NameOffset) );
CurCntr = PerfCntr;
// Get the first counter.
PtrToCntr = (PPERF_COUNTER_BLOCK)((PBYTE)PerfInst +
PerfInst->ByteLength);
// Retrieve all counters.
for( j=0; j < PerfObj->NumCounters; j++ )
{
printf("\t\tCounter: %ld\n",CurCntr->CounterNameTitleIndex);
// Data is (LPVOID)((PBYTE)PtrToCntr + CurCntr->CounterOffset);
// Get next counter.
CurCntr = (PPERF_COUNTER_DEFINITION)((PBYTE)CurCntr +
CurCntr->ByteLength);
}
// Get the next instance.
PerfInst = (PPERF_INSTANCE_DEFINITION)((PBYTE)PtrToCntr +
PtrToCntr->ByteLength);
}
}
else
{
// Get the first counter.
PtrToCntr = (PPERF_COUNTER_BLOCK) ((PBYTE)PerfObj +
PerfObj->DefinitionLength );
// Retrieve all counters.
for( j=0; j < PerfObj->NumCounters; j++ )
{
printf( "\tCounter: %ld\n", PerfCntr->CounterNameTitleIndex );
// Data is (LPVOID)((PBYTE)PtrToCntr + PerfCntr->CounterOffset);
PerfCntr = (PPERF_COUNTER_DEFINITION)((PBYTE)PerfCntr +
PerfCntr->ByteLength);
}
}
// Get the next object type.
PerfObj = (PPERF_OBJECT_TYPE)((PBYTE)PerfObj +
PerfObj->TotalByteLength);
}
}
Note that the instance names are retrieved in a fashion that is similar to
retrieving the data.
The steps above showed how to obtain all of the counters. You can retrieve only the counters that pertain to a particular object by using the titles database. The information is stored in the registry in the format index, name, index, name, and so forth.
To retrieve the titles database and store it in TitlesDatabase:
1. Open the key:
RegOpenKeyEx( HKEY_LOCAL_MACHINE,
"Software\\Microsoft\\Windows NT\\CurrentVersion\\Perflib\\009",
0,
KEY_READ,
&Hkey);
Note that 009 is a language ID, so this value will be different on a
non-English version of the operating system.
2. Query the information from the key:
RegQueryInfoKey(
Hkey,
(LPTSTR) Class,
&ClassSize,
NULL,
&Subkey,
MaxSubKey,
&MaxClass,
&Values,
&MaxName,
&MaxData,
&SecDesc,
&LastWriteTime );
3. Allocate a buffer to store the information:
TitlesDataBase = (PSTR) malloc( (MaxData+1) * sizeof(TCHAR) )
4. Retrieve the data:
RegQueryValueEx( Hkey,
(LPTSTR) "Counters",
NULL,
NULL,
(LPBYTE) TitlesDataBase,
&MaxData );
Once you have the database, it is possible to write code that will go
through all objects, searching by index (field ObjectNameTitleIndex) or by
type (field ObjectNameTitle - which is initially NULL).
Or, you could obtain only the performance data for specified objects by changing the call to ReqQueryValueEx() in step 1 of the SUMMARY section above to:
RegQueryValueEx( HKEY_PERFORMANCE_DATA,
Indices,
NULL,
NULL,
PerfData,
&BufferSize );
Note that the only difference here is that instead of specifying "Global"
as the second parameter, you specify a string that represents the decimal
value(s) for the object(s) of interest that are obtained from the titles
database.
The PVIEWER and PERFMON samples in the MSTOOLS\SAMPLES\SDKTOOLS\WINNT directory contain complete sample code that deals with performance data.
For more information, please see the "Performance Overview" in the Win32 SDK documentation and the volume titled "Optimizing Windows NT" in the Windows NT Resource Kit.
KBCategory: kbprg KBSubcategory: BsePerfmon Additional reference words: 3.10 3.50 3.51 4.00 Perfmon
Keywords : kbKernBase kbPerfMon kbGrpKernBase
Version : 3.10 3.50 3.51 4.00
Platform : NT WINDOWS
Last Reviewed: January 17, 1997