Windows性能计数器
一、性能计数器概述
性能监视,是Windows NT提供的一种系统功能。Windows NT一直以来总是集成了性能监视工具,它提供有关操作系统当前运行状况的信息,针对各种对象提供了数百个性能计数器。性能对象,就是被监视的对象,典型例子有Processor、Process、Memory、TCP/UDP/IP/ICMP、PhysicalDisk等。计数器通常提供操作系统、应用程序、服务、驱动程序等的性能相关信息,以此来分析系统瓶颈和对系统及应用程序性能进行诊断和调优。性能计数器机制让应用程序和操作系统组件可以向性能监视应用程序,比如性能监视器(Performance Monitor),报告一些与性能有关的统计信息。PerfMon.exe中可以查看性能对象、性能计数器和对象实例,可通过添加计数器来查看相关描述信息。
实际上,可以通过编写程序来访问所有的Windows性能计数器。Windows中,注册表是访问性能计数器的一种机制。性能信息并不实际存在于注册表中,在注册表编辑器RegEdit.exe中是无法查看的,但可以通过注册表函数来访问,利用注册表键来获得从性能数据提供者那里提供的数据。打开名为HKEY_PERFORMANCE_DATA的特殊键,利用RegQueryValueEx函数查询键下面的值,就可以直接访问注册表性能计数器信息。当然,也可以利用性能数据帮助器(PDH, Performance Data Helper) API (Pdh.dll)来访问性能计数器信息。
二、相关术语
性能对象(Performance Object):被监视的性能对象,如Processor、Process、Memory、PhysicalDisk等,相当于类(Class)。
性能计数器(Performance Counter):描述性能对象性能信息的方式,相当于类属性。
对象实例(Object Instance):相同性能对象可能有多个,把它们表示为该对象类型的不同实例,相当于类实例。
三、HKEY_PERFORMANCE_DATA数据组织
性能数据的头部是一个PERF_DATA_BLOCK结构(如图1所示),它描述系统和性能数据总体信息,可从Global键值处查询得到该结构数据。PERF_DATA_BLOCK之后,定义了系统中的全部性能对象类型(PERF_OBJECT_TYPE),其中每个对象类型头部中描述了下一个性能对象类型的偏移量Offset。 图1
图2
性能对象有两种:一种是单实例对象,另一种是多实例对象。图2和图3分别描述了这两种性能对象的数据组织方式。每个对象数据块包含了一个PERF_OBJECT_TYPE结构,描述对象的性能数据。紧随其后是PERF_COUNTER_DEFINITION结构列表,描述了性能对象的全部计数器定义。对于单实例对象,计数器定义列表后是一个PERF_COUNTER_BLOCK结构,计数器数据紧随其后。每个PERF_COUNTER_DEFINITION结构中定义了计数器数据相对于PERF_COUNTER_BLOCK的偏移量,因此可以非常方便地获得全部计数器的值。对支持多实例性能对象来说,PERF_COUNTER_DEFINITION结构列表之后是一组实例信息数据块,每个表示代表一个对象实例。每个实例信息数据块由一个PERF_INSTANCE_DEFINITION结构体、实例名和一个PERF_COUNTER_BLOCK结构体组成。后面是计数器值数据,与单实例对象相同。
图3
四、一个简单性能计数器查看器的实现
基于以上的知识和一些参考文献,本人在Windows Xp Sp3 + VS2003环境下实现了一个Windows性能计数器查看器。界面如图4所示,核心部分代码如下:
1、头文件winperf.h
- #ifndef _WINPERF
- #define _WINPERF
- #include "stdafx.h"
- #include <windows.h>
- #include <tchar.h>
- #include <io.h>
- #include <conio.h>
- #include <string.h>
- #include <stdio.h>
- #include <strsafe.h>
- #include <winperf.h>
- #include <String>
- #include <vector>
- #include <map>
- #include <iostream>
- using namespace std;
- #define INITIAL_SIZE 51200
- #define EXTEND_SIZE 25600
- #define PERF_SUBKEY_GLOBAL _T("Global")
- #define REGSUBKEY_COUNTERS _T("Counters")
- typedef map <DWORD, DWORD>::const_iterator CIT;
- BOOL ConnectComputerPerformanceRegistry(LPCSTR lpMachineName, HKEY &hKey);
- BOOL GetNameStrings(HKEY hKey, map <DWORD, LPSTR> &mPerfObjectIndex);
- BOOL EnumPerfObjects(HKEY hKey, vector <PERF_OBJECT_TYPE> &vPerfObjects);
- BOOL LoadObjectData(HKEY hKey, DWORD dwObjIndex, map <DWORD, LPSTR> mPerfCountersIndex, /
- CListBox *pCListBoxCounters, CListCtrl *pCListCtrlInstances);
- #endif
2、连接(远程)计算机性能计数器注册表
- BOOL ConnectComputerPerformanceRegistry(LPCSTR lpMachineName, HKEY &hKey)
- {
- DWORD retCode;
- retCode = RegConnectRegistry(lpMachineName, HKEY_PERFORMANCE_DATA, &hKey);
- return (retCode == ERROR_SUCCESS) ? TRUE : FALSE;
- }
3、枚举性能对象
- static inline PPERF_OBJECT_TYPE FirstObject(PPERF_DATA_BLOCK PerfData)