Windows效能計數器

來源:互聯網
上載者:User

一、效能計數器概述
  效能監控,是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<br />#define _WINPERF</p><p>#include "stdafx.h"<br />#include <windows.h><br />#include <tchar.h><br />#include <io.h><br />#include <conio.h><br />#include <string.h><br />#include <stdio.h><br />#include <strsafe.h><br />#include <winperf.h><br />#include <String><br />#include <vector><br />#include <map><br />#include <iostream><br />using namespace std;</p><p>#define INITIAL_SIZE 51200<br />#define EXTEND_SIZE 25600<br />#define PERF_SUBKEY_GLOBAL_T("Global")<br />#define REGSUBKEY_COUNTERS _T("Counters")</p><p>typedef map <DWORD, DWORD>::const_iterator CIT;</p><p>BOOL ConnectComputerPerformanceRegistry(LPCSTR lpMachineName, HKEY &hKey);<br />BOOL GetNameStrings(HKEY hKey, map <DWORD, LPSTR> &mPerfObjectIndex);<br />BOOL EnumPerfObjects(HKEY hKey, vector <PERF_OBJECT_TYPE> &vPerfObjects);<br />BOOL LoadObjectData(HKEY hKey, DWORD dwObjIndex, map <DWORD, LPSTR> mPerfCountersIndex, /<br />CListBox *pCListBoxCounters, CListCtrl *pCListCtrlInstances);</p><p>#endif
2、串連(遠程)電腦效能計數器註冊表

BOOL ConnectComputerPerformanceRegistry(LPCSTR lpMachineName, HKEY &hKey)<br />{<br />DWORD retCode;</p><p>retCode = RegConnectRegistry(lpMachineName, HKEY_PERFORMANCE_DATA, &hKey);<br />return (retCode == ERROR_SUCCESS) ? TRUE : FALSE;<br />}

3、枚舉效能物件

static inline PPERF_OBJECT_TYPE FirstObject(PPERF_DATA_BLOCK PerfData)<br />{<br />return((PPERF_OBJECT_TYPE)((PBYTE)PerfData + PerfData->HeaderLength));<br />} </p><p>static inline PPERF_OBJECT_TYPE NextObject(PPERF_OBJECT_TYPE PerfObj)<br />{<br />return((PPERF_OBJECT_TYPE)((PBYTE)PerfObj + PerfObj->TotalByteLength));<br />}</p><p>BOOL EnumPerfObjects(HKEY hKey, vector <PERF_OBJECT_TYPE> &vPerfObjects)<br />{<br />DWORD retCode = ERROR_MORE_DATA;<br />DWORD dwType = 0;<br />DWORD dwSize = 0;<br />PPERF_DATA_BLOCK PerfData = (PPERF_DATA_BLOCK)malloc(INITIAL_SIZE);<br />PPERF_OBJECT_TYPE PPerfObj;</p><p>while (retCode == ERROR_MORE_DATA)<br />{<br />dwSize += EXTEND_SIZE;<br />PerfData = (PPERF_DATA_BLOCK)realloc(PerfData, dwSize);<br />retCode = RegQueryValueEx(hKey, PERF_SUBKEY_GLOBAL, 0, &dwType, (LPBYTE)PerfData, &dwSize);<br />}<br />if (retCode != ERROR_SUCCESS)<br />return FALSE;</p><p>PPerfObj = FirstObject(PerfData);<br />for (int i = 0; i < PerfData->NumObjectTypes; i++)<br />{<br />PERF_OBJECT_TYPE PerfObj;<br />memcpy(&PerfObj, PPerfObj, sizeof(PERF_OBJECT_TYPE));<br />vPerfObjects.push_back(PerfObj);<br />PPerfObj = NextObject(PPerfObj);<br />}</p><p>return TRUE;<br />}

4、擷取效能計數器名字

BOOL GetNameStrings(HKEY hKey, map <DWORD, LPSTR> &mPerfObjectIndex)<br />{<br />DWORD retCode = 0;<br />DWORD dwType = 0;<br />DWORD dwSize = 0;<br />LPBYTE buffer = NULL;<br />LPSTR p, p2;<br />LPSTR lpCurrentString;<br />DWORD dwCounter = 0;</p><p>retCode = RegQueryValueEx(hKey, REGSUBKEY_COUNTERS, NULL, &dwType, NULL, &dwSize);<br />if (retCode != ERROR_SUCCESS)<br />{<br />perror("RegQueryValueEx REGSUBKEY_COUNTERS Size");<br />return FALSE;<br />}</p><p>buffer = (LPBYTE)malloc(dwSize);<br />memset(buffer, 0, dwSize);<br />retCode = RegQueryValueEx(hKey, REGSUBKEY_COUNTERS, NULL, &dwType, buffer, &dwSize);<br />if (retCode != ERROR_SUCCESS)<br />{<br />perror("RegQueryValueEx REGSUBKEY_COUNTERS Content");<br />return FALSE;<br />}</p><p>p = (LPSTR) buffer;<br />for(lpCurrentString = p; *lpCurrentString; lpCurrentString += (lstrlen(lpCurrentString) + 1))<br />{<br />dwCounter = atol(lpCurrentString);<br />lpCurrentString += (lstrlen(lpCurrentString) + 1);<br />mPerfObjectIndex[dwCounter] = (LPSTR)lpCurrentString;<br />}</p><p>return TRUE;<br />}

5、枚舉效能物件執行個體和計數器值

BOOL LoadObjectData(HKEY hKey, DWORD dwObjIndex, map <DWORD, LPSTR> mPerfCountersIndex, /<br />CListBox *pCListBoxCounters, CListCtrl *pCListCtrlInstances)<br />{<br />TCHAR szSubKey[1024] = {0};<br />DWORD rt = 0;<br />DWORD dwType = 0;<br />DWORD dwSize = 0;<br />LPBYTE buffer = NULL;<br />BOOL bPass = TRUE;<br />map <DWORD, string> mCounters;<br />map <DWORD, DWORD> mOffsets;<br />map <DWORD, int> mIndexs;</p><p>LPSTR p;<br />PPERF_DATA_BLOCK pPerf;<br />PPERF_OBJECT_TYPE pObj;<br />PPERF_INSTANCE_DEFINITION pInst;<br />PPERF_COUNTER_BLOCK pCounter;<br />PPERF_COUNTER_DEFINITION pCounterDef;</p><p>buffer = NULL;<br />dwSize = INITIAL_SIZE;<br />buffer = (LPBYTE) malloc(dwSize);<br />memset(buffer, 0, dwSize);<br />wsprintf(szSubKey, "%u", dwObjIndex);<br />// get Object PERF_DATA_BLOCK<br />while (bPass)<br />{<br />rt = RegQueryValueEx(hKey, szSubKey, NULL, &dwType, buffer, &dwSize);<br />pPerf = (PPERF_DATA_BLOCK) buffer;<br />if ((rt == ERROR_SUCCESS) && (dwSize > 0) &&<br />pPerf->Signature[0] == (WCHAR)'P' &&<br />pPerf->Signature[1] == (WCHAR)'E' &&<br />pPerf->Signature[2] == (WCHAR)'R' &&<br />pPerf->Signature[3] == (WCHAR)'F')<br />{<br />break;<br />}</p><p>if (rt == ERROR_MORE_DATA)<br />{<br />dwSize += EXTEND_SIZE;<br />buffer = (LPBYTE)realloc(buffer, dwSize );<br />memset(buffer, 0, dwSize );<br />}<br />else<br />{<br />bPass = FALSE;<br />}<br />}</p><p>if (bPass)<br />{<br />// get Counters<br />pObj = (PPERF_OBJECT_TYPE) ((DWORD)pPerf + pPerf->HeaderLength);<br />pCounterDef = (PPERF_COUNTER_DEFINITION) ((DWORD)pObj + pObj->HeaderLength);<br />pCListCtrlInstances->InsertColumn(0, (LPCTSTR)(mPerfCountersIndex[dwObjIndex]), LVCFMT_LEFT, 120);<br />for (DWORD i = 0; i < (DWORD)pObj->NumCounters; i++)<br />{<br />mOffsets[pCounterDef->CounterNameTitleIndex] = pCounterDef->CounterOffset;<br />mIndexs[pCounterDef->CounterNameTitleIndex] = i + 1;<br />pCListBoxCounters->InsertString(i, (LPCTSTR)(mPerfCountersIndex[pCounterDef->CounterNameTitleIndex]));<br />pCListCtrlInstances->InsertColumn(i + 1, (LPCTSTR)(mPerfCountersIndex[pCounterDef->CounterNameTitleIndex]), LVCFMT_LEFT, 120);<br />pCounterDef++;<br />} </p><p>// get instances<br />if (pObj->NumInstances == 0 || PERF_NO_INSTANCES == pObj->NumInstances)<br />{<br />// no instances<br />pCounter = (PPERF_COUNTER_BLOCK)((DWORD)pObj + pObj->DefinitionLength);<br />pCListCtrlInstances->InsertItem(0, "None");<br />for(CIT p = mOffsets.begin(); p != mOffsets.end(); ++p)<br />{<br />DWORD counterVal = *((LPDWORD) ((DWORD)pCounter + p->second));<br />char info[256] = {0};<br />wsprintf(info, "%u", counterVal);<br />pCListCtrlInstances->SetItemText(0, mIndexs[p->first], info);<br />}<br />}<br />else<br />{<br />// muiti-instances case<br />TCHAR szInstanceName[MAX_PATH];<br />pInst = (PPERF_INSTANCE_DEFINITION) ((DWORD)pObj + pObj->DefinitionLength);<br />for (i = 0; i < (DWORD)pObj->NumInstances; i++)<br />{<br />p = (LPSTR) ((DWORD)pInst + pInst->NameOffset);<br />rt = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)p, -1, szInstanceName, sizeof(szInstanceName), NULL, NULL);<br />pCListCtrlInstances->InsertItem(i, szInstanceName);</p><p>for(CIT p = mOffsets.begin(); p != mOffsets.end(); ++p)<br />{<br />pCounter = (PPERF_COUNTER_BLOCK) ((DWORD)pInst + pInst->ByteLength);<br />DWORD counterVal = *((LPDWORD) ((DWORD)pCounter + p->second));</p><p>char info[256] = {0};<br />wsprintf(info, "%u", counterVal);<br />pCListCtrlInstances->SetItemText(i, mIndexs[p->first], info);<br />}<br />// Point to the next process<br />pInst = (PPERF_INSTANCE_DEFINITION) ((DWORD)pCounter + pCounter->ByteLength);<br />}<br />}<br />}// end if (bPass)</p><p>if (buffer)<br />{<br />free(buffer);<br />buffer = NULL;<br />}<br />return bPass;<br />}

五、參考文獻
[1] 深入解析Windows作業系統(第四版), Mark E.Russinovich & David A.Solomon.
[2] Using Performance Counters, MSDN. http://msdn.microsoft.com/en-us/library/aa373209(VS.85).aspx.
[3] 縱談進程枚舉, 陸其明. http://jasonye.bokee.com/432054.html.
[4] 如何編程擷取Windows NT的效能資料, 周京生. http://www.comprg.com.cn/detail.asp?hw_id=2643.

 

(Aiguille LIU / 劉愛貴 / Aigui.liu@gmail.com)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.