MiTec/Common/MiTeC_WinPerf.pas
2024-07-06 22:30:25 +02:00

915 lines
38 KiB
ObjectPascal

{*******************************************************}
{ MiTeC Common Routines }
{ Performance Monitoring API }
{ }
{ Copyright (c) 1997-2016 Michal Mutl }
{ }
{*******************************************************}
{$INCLUDE Compilers.inc}
unit MiTeC_WinPerf;
interface
uses {$IFDEF RAD9PLUS}
WinAPI.Windows, System.SysUtils, System.Classes, System.Variants;
{$ELSE}
Variants, Windows, SysUtils, Classes;
{$ENDIF}
const
PERF_DATA_VERSION = 1;
{$EXTERNALSYM PERF_DATA_VERSION}
PERF_DATA_REVISION = 1;
{$EXTERNALSYM PERF_DATA_REVISION}
type
{$IFNDEF RAD9PLUS}
LONG = Longint;
{$ENDIF}
PPERF_DATA_BLOCK = ^PERF_DATA_BLOCK;
{$EXTERNALSYM PPERF_DATA_BLOCK}
_PERF_DATA_BLOCK = record
Signature: array [0..3] of WCHAR; // Signature: Unicode "PERF"
LittleEndian: DWORD; // 0 = Big Endian, 1 = Little Endian
Version: DWORD; // Version of these data structures
// starting at 1
Revision: DWORD; // Revision of these data structures
// starting at 0 for each Version
TotalByteLength: DWORD; // Total length of data block
HeaderLength: DWORD; // Length of this structure
NumObjectTypes: DWORD; // Number of types of objects
// being reported
DefaultObject: LONG; // Object Title Index of default
// object to display when data from
// this system is retrieved (-1 =
// none, but this is not expected to
// be used)
SystemTime: SYSTEMTIME; // Time at the system under
// measurement
PerfTime: LARGE_INTEGER; // Performance counter value
// at the system under measurement
PerfFreq: LARGE_INTEGER; // Performance counter frequency
// at the system under measurement
PerfTime100nSec: LARGE_INTEGER; // Performance counter time in 100 nsec
// units at the system under measurement
SystemNameLength: DWORD; // Length of the system name
SystemNameOffset: DWORD; // Offset, from beginning of this
// structure, to name of system
// being measured
end;
{$EXTERNALSYM _PERF_DATA_BLOCK}
PERF_DATA_BLOCK = _PERF_DATA_BLOCK;
{$EXTERNALSYM PERF_DATA_BLOCK}
TPerfDataBlock = PERF_DATA_BLOCK;
PPerfDataBlock = PPERF_DATA_BLOCK;
PPerfLibHeader = ^TPerfLibHeader;
TPerfLibHeader = packed record
Signature: array[0..7] of Char;
DataSize: Cardinal;
ObjectCount: Cardinal;
end;
//
// The _PERF_DATA_BLOCK structure is followed by NumObjectTypes of
// data sections, one for each type of object measured. Each object
// type section begins with a _PERF_OBJECT_TYPE structure.
//
PPERF_OBJECT_TYPE = ^PERF_OBJECT_TYPE;
{$EXTERNALSYM PPERF_OBJECT_TYPE}
_PERF_OBJECT_TYPE = record
TotalByteLength: DWORD; // Length of this object definition
// including this structure, the
// counter definitions, and the
// instance definitions and the
// counter blocks for each instance:
// This is the offset from this
// structure to the next object, if
// any
DefinitionLength: DWORD; // Length of object definition,
// which includes this structure
// and the counter definition
// structures for this object: this
// is the offset of the first
// instance or of the counters
// for this object if there is
// no instance
HeaderLength: DWORD; // Length of this structure: this
// is the offset to the first
// counter definition for this
// object
ObjectNameTitleIndex: DWORD; // Index to name in Title Database
ObjectNameTitle: LPWSTR; // Initially NULL, for use by
// analysis program to point to
// retrieved title string
ObjectHelpTitleIndex: DWORD; // Index to Help in Title Database
ObjectHelpTitle: LPWSTR; // Initially NULL, for use by
// analysis program to point to
// retrieved title string
DetailLevel: DWORD; // Object level of detail (for
// controlling display complexity);
// will be min of detail levels
// for all this object's counters
NumCounters: DWORD; // Number of counters in each
// counter block (one counter
// block per instance)
DefaultCounter: LONG; // Default counter to display when
// this object is selected, index
// starting at 0 (-1 = none, but
// this is not expected to be used)
NumInstances: LONG; // Number of object instances
// for which counters are being
// returned from the system under
// measurement. If the object defined
// will never have any instance data
// structures (PERF_INSTANCE_DEFINITION)
// then this value should be -1, if the
// object can have 0 or more instances,
// but has none present, then this
// should be 0, otherwise this field
// contains the number of instances of
// this counter.
CodePage: DWORD; // 0 if instance strings are in
// UNICODE, else the Code Page of
// the instance names
PerfTime: LARGE_INTEGER; // Sample Time in "Object" units
PerfFreq: LARGE_INTEGER; // Frequency of "Object" units in
// counts per second.
end;
{$EXTERNALSYM _PERF_OBJECT_TYPE}
PERF_OBJECT_TYPE = _PERF_OBJECT_TYPE;
{$EXTERNALSYM PERF_OBJECT_TYPE}
TPerfObjectType = PERF_OBJECT_TYPE;
PPerfObjectType = PPERF_OBJECT_TYPE;
const
PERF_NO_INSTANCES = -1; // no instances (see NumInstances above)
{$EXTERNALSYM PERF_NO_INSTANCES}
//
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//
// PERF_COUNTER_DEFINITION.CounterType field values
//
//
// Counter ID Field Definition:
//
// 3 2 2 2 2 1 1 1
// 1 8 4 2 0 6 2 0 8 0
// +--------+--------+----+----+--------+--------+----+----+----------------+
// |Display |Calculation |Time|Counter | |Ctr |Size| |
// |Flags |Modifiers |Base|SubType |Reserved|Type|Fld | Reserved |
// +--------+--------+----+----+--------+--------+----+----+----------------+
//
//
// The counter type is the "or" of the following values as described below
//
// select one of the following to indicate the counter's data size
//
PERF_SIZE_DWORD = $00000000;
{$EXTERNALSYM PERF_SIZE_DWORD}
PERF_SIZE_LARGE = $00000100;
{$EXTERNALSYM PERF_SIZE_LARGE}
PERF_SIZE_ZERO = $00000200; // for Zero Length Fields
{$EXTERNALSYM PERF_SIZE_ZERO}
PERF_SIZE_VARIABLE_LEN = $00000300; // length is in CounterLength Fields
// of Counter Definition struct
{$EXTERNALSYM PERF_SIZE_VARIABLE_LEN}
//
// select one of the following values to indicate the counter field usage
//
PERF_TYPE_NUMBER = $00000000; // a number (not a counter)
{$EXTERNALSYM PERF_TYPE_NUMBER}
PERF_TYPE_COUNTER = $00000400; // an increasing numeric Value
{$EXTERNALSYM PERF_TYPE_COUNTER}
PERF_TYPE_TEXT = $00000800; // a text Fields
{$EXTERNALSYM PERF_TYPE_TEXT}
PERF_TYPE_ZERO = $00000C00; // displays a zero
{$EXTERNALSYM PERF_TYPE_ZERO}
//
// If the PERF_TYPE_NUMBER field was selected, then select one of the
// following to describe the Number
//
PERF_NUMBER_HEX = $00000000; // display as HEX Value
{$EXTERNALSYM PERF_NUMBER_HEX}
PERF_NUMBER_DECIMAL = $00010000; // display as a decimal integer
{$EXTERNALSYM PERF_NUMBER_DECIMAL}
PERF_NUMBER_DEC_1000 = $00020000; // display as a decimal/1000
{$EXTERNALSYM PERF_NUMBER_DEC_1000}
PERF_NUMBER_MASK = $00030000;
{$EXTERNALSYM PERF_NUMBER_MASK}
//
// If the PERF_TYPE_COUNTER value was selected then select one of the
// following to indicate the type of counter
//
PERF_COUNTER_VALUE = $00000000; // display counter Value
{$EXTERNALSYM PERF_COUNTER_VALUE}
PERF_COUNTER_RATE = $00010000; // divide ctr / delta time
{$EXTERNALSYM PERF_COUNTER_RATE}
PERF_COUNTER_FRACTION = $00020000; // divide ctr / base
{$EXTERNALSYM PERF_COUNTER_FRACTION}
PERF_COUNTER_BASE = $00030000; // base value used in fractions
{$EXTERNALSYM PERF_COUNTER_BASE}
PERF_COUNTER_ELAPSED = $00040000; // subtract counter from current time
{$EXTERNALSYM PERF_COUNTER_ELAPSED}
PERF_COUNTER_QUEUELEN = $00050000; // Use Queuelen processing func.
{$EXTERNALSYM PERF_COUNTER_QUEUELEN}
PERF_COUNTER_HISTOGRAM = $00060000; // Counter begins or ends a histogram
{$EXTERNALSYM PERF_COUNTER_HISTOGRAM}
PERF_COUNTER_PRECISION = $00070000; // divide ctr / private clock
{$EXTERNALSYM PERF_COUNTER_PRECISION}
PERF_COUNTER_MASK = $000f0000;
{$EXTERNALSYM PERF_COUNTER_MASK}
//
// If the PERF_TYPE_TEXT value was selected, then select one of the
// following to indicate the type of TEXT data.
//
PERF_TEXT_UNICODE = $00000000; // type of text in text Fields
{$EXTERNALSYM PERF_TEXT_UNICODE}
PERF_TEXT_ASCII = $00010000; // ASCII using the CodePage Fields
{$EXTERNALSYM PERF_TEXT_ASCII}
//
// Timer SubTypes
//
PERF_TIMER_TICK = $00000000; // use system perf. freq for base
{$EXTERNALSYM PERF_TIMER_TICK}
PERF_TIMER_100NS = $00100000; // use 100 NS timer time base units
{$EXTERNALSYM PERF_TIMER_100NS}
PERF_OBJECT_TIMER = $00200000; // use the object timer freq
{$EXTERNALSYM PERF_OBJECT_TIMER}
PERF_TIMEBASE_MASK = $00300000;
{$EXTERNALSYM PERF_TIMEBASE_MASK}
//
// Any types that have calculations performed can use one or more of
// the following calculation modification flags listed here
//
PERF_DELTA_COUNTER = $00400000; // compute difference First
{$EXTERNALSYM PERF_DELTA_COUNTER}
PERF_DELTA_BASE = $00800000; // compute base diff as well
{$EXTERNALSYM PERF_DELTA_BASE}
PERF_INVERSE_COUNTER = $01000000; // show as 1.00-value (assumes:
{$EXTERNALSYM PERF_INVERSE_COUNTER}
PERF_MULTI_COUNTER = $02000000; // sum of multiple instances
{$EXTERNALSYM PERF_MULTI_COUNTER}
//
// Select one of the following values to indicate the display suffix (if any)
//
PERF_DISPLAY_NO_SUFFIX = $00000000; // no suffix
{$EXTERNALSYM PERF_DISPLAY_NO_SUFFIX}
PERF_DISPLAY_PER_SEC = $10000000; // "/sec"
{$EXTERNALSYM PERF_DISPLAY_PER_SEC}
PERF_DISPLAY_PERCENT = $20000000; // "%"
{$EXTERNALSYM PERF_DISPLAY_PERCENT}
PERF_DISPLAY_SECONDS = $30000000; // "secs"
{$EXTERNALSYM PERF_DISPLAY_SECONDS}
PERF_DISPLAY_NOSHOW = $40000000; // value is not displayed
{$EXTERNALSYM PERF_DISPLAY_NOSHOW}
PERF_DISPLAY_MASK = $f0000000;
{$EXTERNALSYM PERF_DISPLAY_MASK}
//
// Predefined counter types
//
// 32-bit Counter. Divide delta by delta time. Display suffix: "/sec"
PERF_COUNTER_COUNTER =
PERF_SIZE_DWORD or PERF_TYPE_COUNTER or PERF_COUNTER_RATE or
PERF_TIMER_TICK or PERF_DELTA_COUNTER or PERF_DISPLAY_PER_SEC;
{$EXTERNALSYM PERF_COUNTER_COUNTER}
// 64-bit Timer. Divide delta by delta time. Display suffix: "%"
PERF_COUNTER_TIMER =
PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_RATE or
PERF_TIMER_TICK or PERF_DELTA_COUNTER or PERF_DISPLAY_PERCENT;
{$EXTERNALSYM PERF_COUNTER_TIMER}
// Queue Length Space-Time Product. Divide delta by delta time. No Display Suffix.
PERF_COUNTER_QUEUELEN_TYPE =
PERF_SIZE_DWORD or PERF_TYPE_COUNTER or PERF_COUNTER_QUEUELEN or
PERF_TIMER_TICK or PERF_DELTA_COUNTER or PERF_DISPLAY_NO_SUFFIX;
{$EXTERNALSYM PERF_COUNTER_QUEUELEN_TYPE}
// Queue Length Space-Time Product. Divide delta by delta time. No Display Suffix.
PERF_COUNTER_LARGE_QUEUELEN_TYPE =
PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_QUEUELEN or
PERF_TIMER_TICK or PERF_DELTA_COUNTER or PERF_DISPLAY_NO_SUFFIX;
{$EXTERNALSYM PERF_COUNTER_LARGE_QUEUELEN_TYPE}
// Queue Length Space-Time Product using 100 Ns timebase.
// Divide delta by delta time. No Display Suffix.
PERF_COUNTER_100NS_QUEUELEN_TYPE =
PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_QUEUELEN or
PERF_TIMER_100NS or PERF_DELTA_COUNTER or PERF_DISPLAY_NO_SUFFIX;
{$EXTERNALSYM PERF_COUNTER_100NS_QUEUELEN_TYPE}
// Queue Length Space-Time Product using Object specific timebase.
// Divide delta by delta time. No Display Suffix.
PERF_COUNTER_OBJ_TIME_QUEUELEN_TYPE =
PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_QUEUELEN or
PERF_OBJECT_TIMER or PERF_DELTA_COUNTER or PERF_DISPLAY_NO_SUFFIX;
{$EXTERNALSYM PERF_COUNTER_OBJ_TIME_QUEUELEN_TYPE}
// 64-bit Counter. Divide delta by delta time. Display Suffix: "/sec"
PERF_COUNTER_BULK_COUNT =
PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_RATE or
PERF_TIMER_TICK or PERF_DELTA_COUNTER or PERF_DISPLAY_PER_SEC;
{$EXTERNALSYM PERF_COUNTER_BULK_COUNT}
// Indicates the counter is not a counter but rather Unicode text Display as text.
PERF_COUNTER_TEXT =
PERF_SIZE_VARIABLE_LEN or PERF_TYPE_TEXT or PERF_TEXT_UNICODE or
PERF_DISPLAY_NO_SUFFIX;
{$EXTERNALSYM PERF_COUNTER_TEXT}
// Indicates the data is a counter which should not be
// time averaged on display (such as an error counter on a serial line)
// Display as is. No Display Suffix.
PERF_COUNTER_RAWCOUNT =
PERF_SIZE_DWORD or PERF_TYPE_NUMBER or PERF_NUMBER_DECIMAL or
PERF_DISPLAY_NO_SUFFIX;
{$EXTERNALSYM PERF_COUNTER_RAWCOUNT}
// Same as PERF_COUNTER_RAWCOUNT except its size is a large integer
PERF_COUNTER_LARGE_RAWCOUNT =
PERF_SIZE_LARGE or PERF_TYPE_NUMBER or PERF_NUMBER_DECIMAL or
PERF_DISPLAY_NO_SUFFIX;
{$EXTERNALSYM PERF_COUNTER_LARGE_RAWCOUNT}
// Special case for RAWCOUNT that want to be displayed in hex
// Indicates the data is a counter which should not be
// time averaged on display (such as an error counter on a serial line)
// Display as is. No Display Suffix.
PERF_COUNTER_RAWCOUNT_HEX =
PERF_SIZE_DWORD or PERF_TYPE_NUMBER or PERF_NUMBER_HEX or
PERF_DISPLAY_NO_SUFFIX;
{$EXTERNALSYM PERF_COUNTER_RAWCOUNT_HEX}
// Same as PERF_COUNTER_RAWCOUNT_HEX except its size is a large integer
PERF_COUNTER_LARGE_RAWCOUNT_HEX =
PERF_SIZE_LARGE or PERF_TYPE_NUMBER or PERF_NUMBER_HEX or
PERF_DISPLAY_NO_SUFFIX;
{$EXTERNALSYM PERF_COUNTER_LARGE_RAWCOUNT_HEX}
// A count which is either 1 or 0 on each sampling interrupt (% busy)
// Divide delta by delta base. Display Suffix: "%"
PERF_SAMPLE_FRACTION =
PERF_SIZE_DWORD or PERF_TYPE_COUNTER or PERF_COUNTER_FRACTION or
PERF_DELTA_COUNTER or PERF_DELTA_BASE or PERF_DISPLAY_PERCENT;
{$EXTERNALSYM PERF_SAMPLE_FRACTION}
// A count which is sampled on each sampling interrupt (queue length)
// Divide delta by delta time. No Display Suffix.
PERF_SAMPLE_COUNTER =
PERF_SIZE_DWORD or PERF_TYPE_COUNTER or PERF_COUNTER_RATE or
PERF_TIMER_TICK or PERF_DELTA_COUNTER or PERF_DISPLAY_NO_SUFFIX;
{$EXTERNALSYM PERF_SAMPLE_COUNTER}
// A label: no data is associated with this counter (it has 0 length)
// Do not display.
PERF_COUNTER_NODATA =
PERF_SIZE_ZERO or PERF_DISPLAY_NOSHOW;
{$EXTERNALSYM PERF_COUNTER_NODATA}
// 64-bit Timer inverse (e.g., idle is measured, but display busy %)
// Display 100 - delta divided by delta time. Display suffix: "%"
PERF_COUNTER_TIMER_INV =
PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_RATE or
PERF_TIMER_TICK or PERF_DELTA_COUNTER or PERF_INVERSE_COUNTER or
PERF_DISPLAY_PERCENT;
{$EXTERNALSYM PERF_COUNTER_TIMER_INV}
// The divisor for a sample, used with the previous counter to form a
// sampled %. You must check for >0 before dividing by this! This
// counter will directly follow the numerator counter. It should not
// be displayed to the user.
PERF_SAMPLE_BASE =
PERF_SIZE_DWORD or PERF_TYPE_COUNTER or PERF_COUNTER_BASE or
PERF_DISPLAY_NOSHOW or
$00000001; // for compatibility with pre-beta versions
{$EXTERNALSYM PERF_SAMPLE_BASE}
// A timer which, when divided by an average base, produces a time
// in seconds which is the average time of some operation. This
// timer times total operations, and the base is the number of opera-
// tions. Display Suffix: "sec"
PERF_AVERAGE_TIMER =
PERF_SIZE_DWORD or PERF_TYPE_COUNTER or PERF_COUNTER_FRACTION or
PERF_DISPLAY_SECONDS;
{$EXTERNALSYM PERF_AVERAGE_TIMER}
// Used as the denominator in the computation of time or count
// averages. Must directly follow the numerator counter. Not dis-
// played to the user.
PERF_AVERAGE_BASE =
PERF_SIZE_DWORD or PERF_TYPE_COUNTER or PERF_COUNTER_BASE or
PERF_DISPLAY_NOSHOW or
$00000002; // for compatibility with pre-beta versions
{$EXTERNALSYM PERF_AVERAGE_BASE}
// A bulk count which, when divided (typically) by the number of
// operations, gives (typically) the number of bytes per operation.
// No Display Suffix.
PERF_AVERAGE_BULK =
PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_FRACTION or
PERF_DISPLAY_NOSHOW;
{$EXTERNALSYM PERF_AVERAGE_BULK}
// 64-bit Timer in object specific units. Display delta divided by
// delta time as returned in the object type header structure. Display suffix: "%"
PERF_OBJ_TIME_TIMER =
PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_RATE or
PERF_OBJECT_TIMER or PERF_DELTA_COUNTER or PERF_DISPLAY_PERCENT;
{$EXTERNALSYM PERF_OBJ_TIME_TIMER}
// 64-bit Timer in 100 nsec units. Display delta divided by
// delta time. Display suffix: "%"
PERF_100NSEC_TIMER =
PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_RATE or
PERF_TIMER_100NS or PERF_DELTA_COUNTER or PERF_DISPLAY_PERCENT;
{$EXTERNALSYM PERF_100NSEC_TIMER}
// 64-bit Timer inverse (e.g., idle is measured, but display busy %)
// Display 100 - delta divided by delta time. Display suffix: "%"
PERF_100NSEC_TIMER_INV =
PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_RATE or
PERF_TIMER_100NS or PERF_DELTA_COUNTER or PERF_INVERSE_COUNTER or
PERF_DISPLAY_PERCENT;
{$EXTERNALSYM PERF_100NSEC_TIMER_INV}
// 64-bit Timer. Divide delta by delta time. Display suffix: "%"
// Timer for multiple instances, so result can exceed 100%.
PERF_COUNTER_MULTI_TIMER =
PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_RATE or
PERF_DELTA_COUNTER or PERF_TIMER_TICK or PERF_MULTI_COUNTER or
PERF_DISPLAY_PERCENT;
{$EXTERNALSYM PERF_COUNTER_MULTI_TIMER}
// 64-bit Timer inverse (e.g., idle is measured, but display busy %)
// Display 100 * _MULTI_BASE - delta divided by delta time.
// Display suffix: "%" Timer for multiple instances, so result
// can exceed 100%. Followed by a counter of type _MULTI_BASE.
PERF_COUNTER_MULTI_TIMER_INV =
PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_RATE or
PERF_DELTA_COUNTER or PERF_MULTI_COUNTER or PERF_TIMER_TICK or
PERF_INVERSE_COUNTER or PERF_DISPLAY_PERCENT;
{$EXTERNALSYM PERF_COUNTER_MULTI_TIMER_INV}
// Number of instances to which the preceding _MULTI_..._INV counter
// applies. Used as a factor to get the percentage.
PERF_COUNTER_MULTI_BASE =
PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_BASE or
PERF_MULTI_COUNTER or PERF_DISPLAY_NOSHOW;
{$EXTERNALSYM PERF_COUNTER_MULTI_BASE}
// 64-bit Timer in 100 nsec units. Display delta divided by delta time.
// Display suffix: "%" Timer for multiple instances, so result can exceed 100%.
PERF_100NSEC_MULTI_TIMER =
PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_DELTA_COUNTER or
PERF_COUNTER_RATE or PERF_TIMER_100NS or PERF_MULTI_COUNTER or
PERF_DISPLAY_PERCENT;
{$EXTERNALSYM PERF_100NSEC_MULTI_TIMER}
// 64-bit Timer inverse (e.g., idle is measured, but display busy %)
// Display 100 * _MULTI_BASE - delta divided by delta time.
// Display suffix: "%" Timer for multiple instances, so result
// can exceed 100%. Followed by a counter of type _MULTI_BASE.
PERF_100NSEC_MULTI_TIMER_INV =
PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_DELTA_COUNTER or
PERF_COUNTER_RATE or PERF_TIMER_100NS or PERF_MULTI_COUNTER or
PERF_INVERSE_COUNTER or PERF_DISPLAY_PERCENT;
{$EXTERNALSYM PERF_100NSEC_MULTI_TIMER_INV}
// Indicates the data is a fraction of the following counter which
// should not be time averaged on display (such as free space over
// total space.) Display as is. Display the quotient as "%".
PERF_RAW_FRACTION =
PERF_SIZE_DWORD or PERF_TYPE_COUNTER or PERF_COUNTER_FRACTION or
PERF_DISPLAY_PERCENT;
{$EXTERNALSYM PERF_RAW_FRACTION}
PERF_LARGE_RAW_FRACTION =
PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_FRACTION or
PERF_DISPLAY_PERCENT;
{$EXTERNALSYM PERF_LARGE_RAW_FRACTION}
// Indicates the data is a base for the preceding counter which should
// not be time averaged on display (such as free space over total space.)
PERF_RAW_BASE =
PERF_SIZE_DWORD or PERF_TYPE_COUNTER or PERF_COUNTER_BASE or
PERF_DISPLAY_NOSHOW or
$00000003; // for compatibility with pre-beta versions
{$EXTERNALSYM PERF_RAW_BASE}
PERF_LARGE_RAW_BASE =
PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_BASE or
PERF_DISPLAY_NOSHOW;
{$EXTERNALSYM PERF_LARGE_RAW_BASE}
// The data collected in this counter is actually the start time of the
// item being measured. For display, this data is subtracted from the
// sample time to yield the elapsed time as the difference between the two.
// In the definition below, the PerfTime field of the Object contains
// the sample time as indicated by the PERF_OBJECT_TIMER bit and the
// difference is scaled by the PerfFreq of the Object to convert the time
// units into seconds.
PERF_ELAPSED_TIME =
PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_ELAPSED or
PERF_OBJECT_TIMER or PERF_DISPLAY_SECONDS;
{$EXTERNALSYM PERF_ELAPSED_TIME}
//
// The following counter type can be used with the preceding types to
// define a range of values to be displayed in a histogram.
//
PERF_COUNTER_HISTOGRAM_TYPE = $80000000; // Counter begins or ends a histogram
{$EXTERNALSYM PERF_COUNTER_HISTOGRAM_TYPE}
//
// This counter is used to display the difference from one sample
// to the next. The counter value is a constantly increasing number
// and the value displayed is the difference between the current
// value and the previous value. Negative numbers are not allowed
// which shouldn't be a problem as long as the counter value is
// increasing or unchanged.
//
PERF_COUNTER_DELTA =
PERF_SIZE_DWORD or PERF_TYPE_COUNTER or PERF_COUNTER_VALUE or
PERF_DELTA_COUNTER or PERF_DISPLAY_NO_SUFFIX;
{$EXTERNALSYM PERF_COUNTER_DELTA}
PERF_COUNTER_LARGE_DELTA =
PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_VALUE or
PERF_DELTA_COUNTER or PERF_DISPLAY_NO_SUFFIX;
{$EXTERNALSYM PERF_COUNTER_LARGE_DELTA}
//
// The precision counters are timers that consist of two counter values:
// 1) the count of elapsed time of the event being monitored
// 2) the "clock" time in the same units
//
// the precition timers are used where the standard system timers are not
// precise enough for accurate readings. It's assumed that the service
// providing the data is also providing a timestamp at the same time which
// will eliminate any error that may occur since some small and variable
// time elapses between the time the system timestamp is captured and when
// the data is collected from the performance DLL. Only in extreme cases
// has this been observed to be problematic.
//
// when using this type of timer, the definition of the
// PERF_PRECISION_TIMESTAMP counter must immediately follow the
// definition of the PERF_PRECISION_*_TIMER in the Object header
//
// The timer used has the same frequency as the System Performance Timer
PERF_PRECISION_SYSTEM_TIMER =
PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_PRECISION or
PERF_TIMER_TICK or PERF_DELTA_COUNTER or PERF_DISPLAY_PERCENT;
{$EXTERNALSYM PERF_PRECISION_SYSTEM_TIMER}
//
// The timer used has the same frequency as the 100 NanoSecond Timer
PERF_PRECISION_100NS_TIMER =
PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_PRECISION or
PERF_TIMER_100NS or PERF_DELTA_COUNTER or PERF_DISPLAY_PERCENT;
{$EXTERNALSYM PERF_PRECISION_100NS_TIMER}
//
// The timer used is of the frequency specified in the Object header's
// PerfFreq field (PerfTime is ignored)
PERF_PRECISION_OBJECT_TIMER =
PERF_SIZE_LARGE or PERF_TYPE_COUNTER or PERF_COUNTER_PRECISION or
PERF_OBJECT_TIMER or PERF_DELTA_COUNTER or PERF_DISPLAY_PERCENT;
{$EXTERNALSYM PERF_PRECISION_OBJECT_TIMER}
//
// This is the timestamp to use in the computation of the timer specified
// in the previous description block
PERF_PRECISION_TIMESTAMP = PERF_LARGE_RAW_BASE;
{$EXTERNALSYM PERF_PRECISION_TIMESTAMP}
//
// The following are used to determine the level of detail associated
// with the counter. The user will be setting the level of detail
// that should be displayed at any given time.
//
//
PERF_DETAIL_NOVICE = 100; // The uninformed can understand it
{$EXTERNALSYM PERF_DETAIL_NOVICE}
PERF_DETAIL_ADVANCED = 200; // For the advanced user
{$EXTERNALSYM PERF_DETAIL_ADVANCED}
PERF_DETAIL_EXPERT = 300; // For the expert user
{$EXTERNALSYM PERF_DETAIL_EXPERT}
PERF_DETAIL_WIZARD = 400; // For the system designer
{$EXTERNALSYM PERF_DETAIL_WIZARD}
//
//
// There is one of the following for each of the
// PERF_OBJECT_TYPE.NumCounters. The Unicode names in this structure MUST
// come from a message file.
//
//
type
PPERF_COUNTER_DEFINITION = ^PERF_COUNTER_DEFINITION;
{$EXTERNALSYM PPERF_COUNTER_DEFINITION}
_PERF_COUNTER_DEFINITION = record
ByteLength: DWORD; // Length in bytes of this structure
CounterNameTitleIndex: DWORD; // Index of Counter name into
// Title Database
CounterNameTitle: LPWSTR; // Initially NULL, for use by
// analysis program to point to
// retrieved title string
CounterHelpTitleIndex: DWORD; // Index of Counter Help into
// Title Database
CounterHelpTitle: LPWSTR; // Initially NULL, for use by
// analysis program to point to
// retrieved title string
DefaultScale: LONG; // Power of 10 by which to scale
// chart line if vertical axis is 100
// 0 ==> 1, 1 ==> 10, -1 ==>1/10, etc.
DetailLevel: DWORD; // Counter level of detail (for
// controlling display complexity)
CounterType: DWORD; // Type of counter
CounterSize: DWORD; // Size of counter in bytes
CounterOffset: DWORD; // Offset from the start of the
// PERF_COUNTER_BLOCK to the first
// byte of this counter
end;
{$EXTERNALSYM _PERF_COUNTER_DEFINITION}
PERF_COUNTER_DEFINITION = _PERF_COUNTER_DEFINITION;
{$EXTERNALSYM PERF_COUNTER_DEFINITION}
TPerfCounterDefinition = PERF_COUNTER_DEFINITION;
PPerfCounterDefinition = PPERF_COUNTER_DEFINITION;
//
//
// If (PERF_DATA_BLOCK.NumInstances >= 0) then there will be
// PERF_DATA_BLOCK.NumInstances of a (PERF_INSTANCE_DEFINITION
// followed by a PERF_COUNTER_BLOCK followed by the counter data fields)
// for each instance.
//
// If (PERF_DATA_BLOCK.NumInstances < 0) then the counter definition
// strucutre above will be followed by only a PERF_COUNTER_BLOCK and the
// counter data for that COUNTER.
//
const
PERF_NO_UNIQUE_ID = -1;
{$EXTERNALSYM PERF_NO_UNIQUE_ID}
type
PPERF_INSTANCE_DEFINITION = ^PERF_INSTANCE_DEFINITION;
{$EXTERNALSYM PPERF_INSTANCE_DEFINITION}
_PERF_INSTANCE_DEFINITION = record
ByteLength: DWORD; // Length in bytes of this structure,
// including the subsequent name
ParentObjectTitleIndex: DWORD; // Title Index to name of "parent"
// object (e.g., if thread, then
// process is parent object type);
// if logical drive, the physical
// drive is parent object type
ParentObjectInstance: DWORD; // Index to instance of parent object
// type which is the parent of this
// instance.
UniqueID: LONG; // A unique ID used instead of
// matching the name to identify
// this instance, -1 = none
NameOffset: DWORD; // Offset from beginning of
// this struct to the Unicode name
// of this instance
NameLength: DWORD; // Length in bytes of name; 0 = none
// this length includes the characters
// in the string plus the size of the
// terminating NULL AnsiChar. It does not
// include any additional pad bytes to
// correct structure alignment
end;
{$EXTERNALSYM _PERF_INSTANCE_DEFINITION}
PERF_INSTANCE_DEFINITION = _PERF_INSTANCE_DEFINITION;
{$EXTERNALSYM PERF_INSTANCE_DEFINITION}
TPerfInstanceDefinition = PERF_INSTANCE_DEFINITION;
PPerfInstanceDefinition = PPERF_INSTANCE_DEFINITION;
//
// If .ParentObjectName is 0, there
// is no parent-child hierarchy for this object type. Otherwise,
// the .ParentObjectInstance is an index, starting at 0, into the
// instances reported for the parent object type. It is only
// meaningful if .ParentObjectName is not 0. The purpose of all this
// is to permit reporting/summation of object instances like threads
// within processes, and logical drives within physical drives.
//
//
// The PERF_INSTANCE_DEFINITION will be followed by a PERF_COUNTER_BLOCK.
//
PPERF_COUNTER_BLOCK = ^PERF_COUNTER_BLOCK;
{$EXTERNALSYM PPERF_COUNTER_BLOCK}
_PERF_COUNTER_BLOCK = record
ByteLength: DWORD; // Length in bytes of this structure,
// including the following counters
end;
{$EXTERNALSYM _PERF_COUNTER_BLOCK}
PERF_COUNTER_BLOCK = _PERF_COUNTER_BLOCK;
{$EXTERNALSYM PERF_COUNTER_BLOCK}
TPerfCounterBlock = PERF_COUNTER_BLOCK;
PPerfCounterBlock = PPERF_COUNTER_BLOCK;
//
// The PERF_COUNTER_BLOCK is followed by PERF_OBJECT_TYPE.NumCounters
// number of counters.
//
//
// Support for New Extensible API starting with NT 5.0
//
const
PERF_QUERY_OBJECTS = DWORD($80000000);
{$EXTERNALSYM PERF_QUERY_OBJECTS}
PERF_QUERY_GLOBAL = DWORD($80000001);
{$EXTERNALSYM PERF_QUERY_GLOBAL}
PERF_QUERY_COSTLY = DWORD($80000002);
{$EXTERNALSYM PERF_QUERY_COSTLY}
//
// function typedefs for extensible counter function prototypes
//
type
PM_OPEN_PROC = function(Arg1: LPWSTR): DWORD; stdcall;
{$EXTERNALSYM PM_OPEN_PROC}
PM_COLLECT_PROC = function(Arg1: LPWSTR; Arg2: Pointer; Arg3, Arg4: LPDWORD): DWORD; stdcall;
{$EXTERNALSYM PM_COLLECT_PROC}
PM_CLOSE_PROC = function: DWORD; stdcall;
{$EXTERNALSYM PM_CLOSE_PROC}
PM_QUERY_PROC = function(Arg1: LPDWORD; Arg2: Pointer; Arg3, Arg4: LPDWORD): DWORD; stdcall;
{$EXTERNALSYM PM_QUERY_PROC}
const
MAX_PERF_OBJECTS_IN_QUERY_FUNCTION = LONG(64);
{$EXTERNALSYM MAX_PERF_OBJECTS_IN_QUERY_FUNCTION}
//
// The following are the possible values for
// HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\EventLogLevel
// The default is WINPERF_LOG_NONE if the registry value is not defined.
// This should be adopted by all perfdlls to avoid flooding the application
// event log.
//
const
WINPERF_LOG_NONE = 0; // No event reported
{$EXTERNALSYM WINPERF_LOG_NONE}
WINPERF_LOG_USER = 1; // Report only errors
{$EXTERNALSYM WINPERF_LOG_USER}
WINPERF_LOG_DEBUG = 2; // Report debug errors as well
{$EXTERNALSYM WINPERF_LOG_DEBUG}
WINPERF_LOG_VERBOSE = 3; // Report everything
{$EXTERNALSYM WINPERF_LOG_VERBOSE}
function GetCounterTypeStr(AType: DWORD): string;
implementation
// 3 2 2 2 2 1 1 1
// 1 8 4 2 0 6 2 0 8 0
// +--------+--------+----+----+--------+--------+----+----+----------------+
// |Display |Calculation |Time|Counter | |Ctr |Size| |
// |Flags |Modifiers |Base|SubType |Reserved|Type|Fld | Reserved |
// +--------+--------+----+----+--------+--------+----+----+----------------+
function GetCounterTypeStr(AType: DWORD): string;
var
CtrType,
CtrSubType: integer;
begin
CtrType:=AType and $c00;
CtrSubType:=AType and $f0000;
Result:='';
case AType of
PERF_COUNTER_COUNTER: Result:='PERF_COUNTER_COUNTER';
PERF_COUNTER_TIMER: Result:='PERF_COUNTER_TIMER';
PERF_COUNTER_QUEUELEN_TYPE: Result:='PERF_COUNTER_QUEUELEN_TYPE';
PERF_COUNTER_LARGE_QUEUELEN_TYPE: Result:='PERF_COUNTER_LARGE_QUEUELEN_TYPE';
PERF_COUNTER_BULK_COUNT: Result:='PERF_COUNTER_BULK_COUNT';
PERF_COUNTER_TEXT: Result:='PERF_COUNTER_TEXT';
PERF_COUNTER_RAWCOUNT: Result:='PERF_COUNTER_RAWCOUNT';
PERF_COUNTER_LARGE_RAWCOUNT: Result:='PERF_COUNTER_LARGE_RAWCOUNT';
PERF_COUNTER_RAWCOUNT_HEX: Result:='PERF_COUNTER_RAWCOUNT_HEX';
PERF_COUNTER_LARGE_RAWCOUNT_HEX: Result:='PERF_COUNTER_LARGE_RAWCOUNT_HEX';
PERF_SAMPLE_FRACTION: Result:='PERF_SAMPLE_FRACTION';
PERF_SAMPLE_COUNTER: Result:='PERF_SAMPLE_COUNTER';
PERF_COUNTER_NODATA: Result:='PERF_COUNTER_NODATA';
PERF_COUNTER_TIMER_INV: Result:='PERF_COUNTER_TIMER_INV';
PERF_SAMPLE_BASE: Result:='PERF_SAMPLE_BASE';
PERF_AVERAGE_TIMER: Result:='PERF_AVERAGE_TIMER';
PERF_AVERAGE_BASE: Result:='PERF_AVERAGE_BASE';
PERF_AVERAGE_BULK: Result:='PERF_AVERAGE_BULK';
PERF_100NSEC_TIMER: Result:='PERF_100NSEC_TIMER';
PERF_100NSEC_TIMER_INV: Result:='PERF_100NSEC_TIMER_INV';
PERF_COUNTER_MULTI_TIMER: Result:='PERF_COUNTER_MULTI_TIMER';
PERF_COUNTER_MULTI_TIMER_INV: Result:='PERF_COUNTER_MULTI_TIMER_INV';
PERF_COUNTER_MULTI_BASE: Result:='PERF_COUNTER_MULTI_BASE';
PERF_100NSEC_MULTI_TIMER: Result:='PERF_100NSEC_MULTI_TIMER';
PERF_100NSEC_MULTI_TIMER_INV: Result:='PERF_100NSEC_MULTI_TIMER_INV';
PERF_RAW_FRACTION: Result:='PERF_RAW_FRACTION';
PERF_RAW_BASE: Result:='PERF_RAW_BASE';
PERF_ELAPSED_TIME: Result:='PERF_ELAPSED_TIME';
PERF_COUNTER_HISTOGRAM_TYPE: Result:='PERF_COUNTER_HISTOGRAM_TYPE';
PERF_COUNTER_DELTA: Result:='PERF_COUNTER_DELTA';
PERF_COUNTER_LARGE_DELTA: Result:='PERF_COUNTER_LARGE_DELTA';
end;
if Result='' then
case CtrType of
PERF_TYPE_NUMBER :
case CtrSubType of
PERF_NUMBER_HEX: Result:='PERF_NUMBER_HEX';
PERF_NUMBER_DECIMAL: Result:='PERF_NUMBER_DEC';
PERF_NUMBER_DEC_1000: Result:='PERF_NUMBER_DEC1000';
end;
PERF_TYPE_COUNTER:
case CtrSubType of
PERF_COUNTER_VALUE: Result:='PERF_COUNTER_VALUE';
PERF_COUNTER_RATE : Result:='PERF_COUNTER_RATE';
PERF_COUNTER_FRACTION: Result:='PERF_COUNTER_FRACTION';
PERF_COUNTER_BASE: Result:='PERF_COUNTER_BASE';
PERF_COUNTER_ELAPSED: Result:='PERF_COUNTER_ELAPSED';
PERF_COUNTER_QUEUELEN: Result:='PERF_COUNTER_QUEUELEN';
PERF_COUNTER_HISTOGRAM: Result:='PERF_COUNTER_HISTOGRAM';
end;
PERF_TYPE_TEXT:
case CtrSubType of
PERF_TEXT_UNICODE: Result:='PERF_TEXT_UNICODE';
PERF_TEXT_ASCII: Result:='PERF_TEXT_ASCII';
end;
PERF_TYPE_ZERO: Result:='PERF_TYPE_ZERO';
end;
if Result='' then
Result:='0x'+IntToHex(AType,8);
end;
end.