性能监视计数器封装组件PDHWrapper说明
版本
创建时间
创建人
备注
1.0.0112.2
2002-7-12
zhengyun_ustc
第一稿
想要源代码的,请点击:[url=http://211.136.26.243/pdhwrapper.rar]http://211.136.26.243/pdhwrapper.rar[url=http://www.bjums.com/pdhwrapper.rar][/url]
引言:
编写目的:
本文档将说明性能监视封装组件PDHWrapper的作用、接口定义,以及示例。
名词和缩写定义:
1. PDH: Performance Data Helper
2.
概述:
Microsoft Windwos NT/2000 提供了一个强大的API集来访问系统事件和性能数据的众多计数器。我们既可以实时地得到计数器的值,也可以从一个日志文件中读取计数器数据。
Microsoft提供的是Performance Monitoring Functions。一个最基本的使用PDH搜集性能数据的步骤是:
u 创建一个查询;
u 把感兴趣的计数器添加到查询中;
u 搜集性能数据;
u 得到计数器的数值;
u 关闭查询。
我把这些细节操作进行封装,这就是PDHWrapper组件的IPDH接口。对于调用者来说,只需要调用一个属性就可以完成一切,使用起来极其简单。
调用示范:
longCounterValue = oPDH.counter("\Process(_Total)\Handle Count")
简单吧?
这个PDHWrapper组件需要Microsoft的PDH.DLL,这个组件一般说来在系统中是没有的。只有安装了Microsoft Platform SDK,才会在Winnt\System32目录找到它。
我的机器上的这个PDH.DLL的版本号是5.00.2195.2739,全称是Windows Performance Data Helper DLL,是151KB。
经常会用到的计数器,分成下面几类:
1:内存性能:
"Memory:Avaiable Bytes"计数器以便较精确地估计内存的使用情况。这个计数器表示当前的可用内存。
"Memory:Page Faults/sec"和"Memory:Page Reads/sec"计数器测量内存性能。当进程所引用的虚拟内存页不在内存中时,将发生页错误,"Memory:Page Faults/sec"表示页错误的个数。如果某页已在主内存中,或者它正被共享此页的其他进程使用,那么就不会从磁盘调入该页。"Page Reads/sec"是读取磁盘,以提取解决页错误所需页的次数。从总体上讲,这两个计数器反映了访问磁盘的频率,其值越低,说明响应时间越短。
2:IIS
"Internet Information Server Global:Cache Hits%"计数器,它也被称为“高速缓存命中率”,是高速缓存命中数和所有高速缓存请求的比率。
"Internet Information Server Global:Cache flushes",它是缓存数据的有效期,以秒为单位,超过这个时间,则缓存数据过期。如果有效期太短,从缓存中清除数据的频率太高,则不能满足实际要求;如果有效期太长,无用数据不能及时从内存中清除,则会产生内存的浪费。
3:网络性能:
"NBT Connection:Bytes Total/sec"是指本地计算机发送和接收数据的速度。为了查看网络连接是否成为瓶颈,将这个计数器的数据速度与网卡总带宽进行比较。
“Web Service:Maximum Connections(最大连接数)”、“Web Service:Total Connection Attempts(连接尝试总数)”和“Web Service:Connection Refused(被拒绝的连接数)”,来决定Web服务是否使用了足够多的连接。
4:处理器性能:
System:% Total Processor Time :是计算机上所有处理器进行有用工作所花费时间的比例。
Processor:% Processor Time :是处理器用于处理有效工作的时间比。
Process:% Processor Time :是某进程的所有线程使用处理器来运行命令所花费时间的百分比。
NBT Connection:Bytes Total/sec:是本地计算机发送和接收数据的速度。
System:Processor Queue Length :是处理器队列的瞬间长度,以线程为单位。
Processor:Interrupts/sec :是处理器所遇到的设备中断次数。
Processor:%DPC Time:是处理器花费在延迟的过程调用(Deferred Procedure Call)上的时间百分比。
运行环境规定:
Microsoft Windows 2000 Server。
IPDH Reference:
IPDH Interface Reference:
Remarks:
counter property:
这个属性使用起来很简单。就像ADO的Recordset一样,支持这样的语法:recordset(“SomeFieldName”),得到的就是这个数据集的字段的值。我们这里也是,不用关心是否创建了查询,是否添加了计数器,只要传递的计数器的名字是正确的,就可以得到实时的数值。
explain property:
使用办法同上。只要传递计数器的名字,返回值就是计数器的解释性文字。不过这不一定能得到。
count property:
这是当前查询中的计数器的总数目。
Requirements:
Supported platforms include Microsoft Windows® 2000.
Implementation: PDHWrapper.dll, PDHWrapper.lib.
输入项[C/C++]
Header and IDL files: PDHWrapper.h, PDHWrapper.idl
Version-InDependent ProgID: PDHWrapper.PDH
Version-InDependent CLSID: { 76CB53AF-BD5E-4BC0-892E-E5AAFA4E2046 }
IPDH Members
Properties:
Property Name
Property Description
counter
输入的参数是计数器的名字;
首先察看是否已经订阅了这个计数器,如果没有,就添加它;
然后搜集性能数据;
最后把这个计数器的数值返回
count
订阅的计数器的数目
explain
计数器的说明文字
counter property (PDH/IPDH)
我们内置了一个std::map对象,它来存储计数器的名字和句柄。当用户调用counter属性查询计数器时,我们首先查找map中是否有这号人物。如果没有的话,就调用PdhAddCounter方法告诉本次查询我们要订阅这个计数器了。
接着,调用PdhCollectQueryData方法更新计数器中的数据。
之后,我们调用PdhGetFormattedCounterValue来得到这个计数器数值的LONG类型值。
至于,打开和关闭本次Query, 都是放在构造函数和析构函数中做的,不用用户劳神了。
Usage:
[Script]
Script SyntaxlongCounterValue = oPDH.counter(strCounterName)
Parameters
strCounterName
Pointer to the fully-qualified and resolved path of the counter to create. This path can contain wildcard characters.
Example<%@language=VBScript%>
<%
Dim oPDH
Set oPDH = Server.CreateObject("PDHWrapper.PDH")
Dim strCounterName
Dim longCounterValue
StrCounterName = “\Process(_Total)\Handle Count” ‘ 句柄数目
longCounterValue = oPDH.counter(strCounterName) ‘ 计数器的数值
set oPDH = nothing
%>
[Visual Basic]
Visual Basic Syntax
bResult = oSMReceive.ReceiveXML(strMSgContent)
Parameters
strCounterName
Pointer to the fully-qualified and resolved path of the counter to create. This path can contain wildcard characters.
ExampleDim oPDH As New PDHWrapper.PDH
longCounterValue = oPDH.counter(“\Process(_Total)\Handle Count”)
[C/C++]
C/C++ SyntaxHRESULT CPDH::get_counter(VARIANT* Key, VARIANT* pRetItem);
Parameters
Key[in]:
计数器的名字
pRetItem[out,retval]:
计数器的数值
C/C++ Return Values
S_OK
Remarks:
如果输入参数不正确,则返回的VARIANT变量为VT_EMPTY。
由于计数器太多的话,对系统性能有很大的影响,所以我们设置了一个限制。最多只能添加50个计数器,如果超过的话,返回的VARIANT变量也为VT_EMPTY。
count property (PDH/IPDH)
这里返回的是我们内置的std::map对象的size()。
Usage:
[Script]
Script SyntaxnCounterNumber = oPDH.count()
Example<%@language=VBScript%>
<%
Dim oPDH
Set oPDH = Server.CreateObject("PDHWrapper.PDH")
Dim nCounterNumber
nCounterNumber = oPDH.count ‘ 计数器的总数目
set oPDH = nothing
%>
[Visual Basic]
Visual Basic SyntaxnCounterNumber = oPDH.count()
ExampleDim oPDH As New PDHWrapper.PDH
nCounterNumber = oPDH.count
[C/C++]
C/C++ SyntaxHRESULT CPDH::get_count(long* pCount);
Parameters
pCount[out,retval]:
计数器的总数目
C/C++ Return Values
S_OK
explain property (PDH/IPDH)
用户可以自由察看任何一个计数器的说明。如果我们在std::map对象中没有找到本计数器,就添加一个,但是获得计数器的说明之后 ,就把这个计数器删除。如果在此之前已经订阅了本计数器,则不删除它。
Usage:
[Script]
Script SyntaxszExplainText = oPDH.explain(strCounterName)
Parameters
strCounterName
Pointer to the fully-qualified and resolved path of the counter to create. This path can contain wildcard characters.
Example<%@language=VBScript%>
<%
Dim oPDH
Set oPDH = Server.CreateObject("PDHWrapper.PDH")
Dim strCounterName
Dim strExplainText
StrCounterName = “\Process(_Total)\Handle Count” ‘ 句柄数目
strExplainText = oPDH.explain(strCounterName) ‘ 计数器的解释
set oPDH = nothing
%>
[Visual Basic]
Visual Basic SyntaxszExplainText = oPDH.explain(strCounterName)
Parameters
strCounterName
Pointer to the fully-qualified and resolved path of the counter to create. This path can contain wildcard characters.
ExampleDim oPDH As New PDHWrapper.PDH
strExplainText = oPDH.explain(“\\zhengyun\Process(_Total)\Handle Count”)
[C/C++]
C/C++ SyntaxHRESULT CPDH::get_explain(VARIANT* Key, VARIANT* pRetItem);
Parameters
Key[in]:
计数器的名字
pRetItem[out,retval]:
计数器的说明
C/C++ Return Values
S_OK
Remarks:
如果输入参数不正确,则返回的VARIANT变量为VT_EMPTY。
如果参数是一个代表计数器名字的BSTR,则
第一步,调用PdhAddCounter来添加计数器;
第二步,PdhGetCounterInfo得到这个计数器的PDH_COUNTER_INFO结构;
第三步,得到计数器的PDH_COUNTER_INFO结构的szExplainText。
必要时,调用PdhRemoveCounter方法将这个计数器从查询中删除。
Using IPDH Interface:
下面的ASP例子将给出查询性能指标的全部流程。
Example:
<%@ Language=VBScript %>
Dim obj
Set obj = Server.CreateObject("PDHWrapper.PDH")
Repsonse.Write obj.counter("\Process(_Total)\Handle Count")
Repsonse.Write obj.counter("\Process(_Total)\Handle Count")
Repsonse.Write obj.counter("\\server.tomosoft.com\Process(_Total)\Handle Count")
Repsonse.Write obj.counter("\\zhengyun\Process(_Total)\Thread Count")
Repsonse.Write obj.explain("\Process(_Total)\Handle Count")
Repsonse.Write obj.count
%>