Bug of performance counter API or perfmon tool

Discussion in 'C++' started by George2, Jan 25, 2008.

  1. George2

    George2 Guest

    Hello everyone,


    I found using performance counter API and using perfmon counter will
    result in different numeric result. Here is an example, and in the
    example code, virtual bytes is always larger than working set, but in
    perfmon, working set is always larger than working set.

    Any ideas?

    Code:
    #include <windows.h>
    #include <stdio.h>
    #include <pdh.h>
    #include <atltime.h>
    
    #pragma comment(lib, "pdh")
    
    PDH_STATUS ps;
    CHAR wsPath[256];
    CHAR vbPath[256];
    DWORD wsItems = 0;
    DWORD wsSize  = 0;
    DWORD vbItems = 0;
    DWORD vbSize  = 0;
    
    FILE* fLog = fopen("perfcount.log", "w+");
    
    CHAR processModule[MAX_PATH] = {0};
    
    CHAR* GetProcModuleName()
    {
    	if (GetModuleFileName(GetModuleHandle(NULL), processModule,
    sizeof(processModule)))
    	{
    		CHAR* p = strrchr(processModule, '.');
    		if (p)
    			*p = '\0';
    		else
    			return NULL;
    		p = strrchr(processModule, '\\');
    		if (p)
    			return (p + 1);
    	}
    
    	return NULL;
    }
    
    void GetCounters(DWORD sectionIndex)
    {
    	HQUERY hQuery;
    	HCOUNTER hWsCount;
    	HCOUNTER hVbCount;
    
    	ps = PdhOpenQuery(NULL, 0, &hQuery);
    	ps = PdhAddCounter(hQuery, wsPath, 0, &hWsCount);
    	ps = PdhAddCounter(hQuery, vbPath, 0, &hVbCount);
    
    	ps = PdhCollectQueryData(hQuery);
    
    	wsItems = 0;
    	wsSize  = 0;
    	vbItems = 0;
    	vbSize  = 0;
    	PDH_RAW_COUNTER_ITEM* pWS = NULL;
    	PDH_RAW_COUNTER_ITEM* pVB = NULL;
    
    	ps = PdhGetRawCounterArray(hWsCount, &wsSize, &wsItems, NULL);
    	pWS = (PDH_RAW_COUNTER_ITEM*)LocalAlloc(LPTR, wsSize);
    	ps = PdhGetRawCounterArray(hVbCount, &vbSize, &vbItems, NULL);
    	pVB = (PDH_RAW_COUNTER_ITEM*)LocalAlloc(LPTR, vbSize);
    	ps = PdhGetRawCounterArray(hWsCount, &wsSize, &wsItems, pWS);
    	ps = PdhGetRawCounterArray(hVbCount, &vbSize, &vbItems, pVB);
    	ps = PdhCloseQuery(hQuery);
    
    	CTime t = pWS->RawValue.TimeStamp;
    	fprintf(fLog, "[%s] SI: %6d\t WS: %.2f Mb\tVB: %.2f Mb\n",
    		t.Format("%c"),
    		sectionIndex,
    		double(pWS->RawValue.FirstValue) /1024 /1024,
    		double(pVB->RawValue.FirstValue) /1024 /1024);
    	LocalFree(pWS);
    	LocalFree(pVB);
    	fflush(fLog);
    }
    
    
    int main(int argc, char* argv[])
    {
    	LARGE_INTEGER start,end;
    	LARGE_INTEGER freq;
    	QueryPerformanceCounter(&start);
    	QueryPerformanceFrequency(&freq);
    
    	MEMORYSTATUS memstat;
    	void** map;
    	int sectionIndex = 0;
    	memstat.dwLength = sizeof(memstat);
    	GlobalMemoryStatus(&memstat);
    
    	// basic file mapping test (512 MB)
    	long long size = 512*1024*1024;
    
    
    	DWORD nsize = 0;
    	CHAR poName[256];
    	CHAR wsName[256];
    	CHAR vbName[256];
    
    	nsize = sizeof(poName);
    	ps = PdhLookupPerfNameByIndex(NULL, 230, poName, &nsize);  // Process
    object
    	nsize = sizeof(wsName);
    	ps = PdhLookupPerfNameByIndex(NULL, 180, wsName, &nsize);  // Working
    Set counter
    	nsize = sizeof(vbName);
    	ps = PdhLookupPerfNameByIndex(NULL, 174, vbName, &nsize);  // Virtual
    Bytes counter
    
    	PDH_COUNTER_PATH_ELEMENTS pcpe = {0};
    	pcpe.szObjectName = poName;
    	pcpe.szInstanceName = GetProcModuleName();
    
    	pcpe.szCounterName = wsName;
    	nsize = sizeof(wsPath);
    	ps = PdhMakeCounterPath(&pcpe, wsPath, &nsize, 0);
    
    	pcpe.szCounterName = vbName;
    	nsize = sizeof(vbPath);
    	ps = PdhMakeCounterPath(&pcpe, vbPath, &nsize, 0);
    
    	HANDLE mapping =
    	CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE|SEC_COMMIT,
    (DWORD)(size>>32),DWORD(size),NULL);
    	if (mapping)
    	{
    		// create and destroy temporary views
    		SYSTEM_INFO sysInfo;
    		GetSystemInfo(&sysInfo);
    		const int allocSize = sysInfo.dwAllocationGranularity;
    
    		GlobalMemoryStatus(&memstat);
    
    		void *mem = new char[allocSize];
    		memset(mem,0x11,allocSize);
    
    		map = (void**) new char [sizeof(void*) * size / allocSize];
    
    		for (int i=0; i<1; i++)
    		{
    
    			sectionIndex = 0;
    			for (long long offset=0; offset<=size-allocSize; offset
    +=allocSize)
    			{
    				map [sectionIndex] =
    				MapViewOfFile(mapping,FILE_MAP_WRITE,(DWORD)(offset>>32),
    (DWORD)offset,allocSize);
    				if (map [sectionIndex])
    				{
    					memcpy(map [sectionIndex],mem,allocSize);
    
    					GetCounters(sectionIndex);
    
    					// UnmapViewOfFile(map);
    				}
    
    				sectionIndex++;
    			} // for (long long offset=0; offset<=size-allocSize; offset
    +=allocSize)
    
    			// close mapped files to avoid leak
    			for (sectionIndex = 0; sectionIndex < size/allocSize; sectionIndex+
    +)
    			{
    				if (map [sectionIndex])
    				{
    					UnmapViewOfFile(map [sectionIndex]);
    				}
    			}
    
    			GlobalMemoryStatus(&memstat);
    
    			sectionIndex = 0;
    			for (long long offset=0; offset<=size-allocSize; offset
    +=allocSize)
    			{
    				map [sectionIndex] =
    				MapViewOfFile(mapping,FILE_MAP_READ,(DWORD)(offset>>32),
    (DWORD)offset,allocSize);
    				if (map [sectionIndex])
    				{
    					for (int t=0; t<allocSize; t++)
    					{
    						if (((char *)(map [sectionIndex]))[t]!=0x11)
    						{
    							OutputDebugString("Memory read failed\n");
    						}
    					}
    
    					GetCounters(sectionIndex);
    				}
    
    				UnmapViewOfFile(map [sectionIndex]);
    				sectionIndex++;
    			}
    
    			// close mapped files to avoid leak
    			/*
    			for (sectionIndex = 0; sectionIndex < size/allocSize; sectionIndex+
    +)
    			{
    				if (map [sectionIndex])
    				{
    					UnmapViewOfFile(map [sectionIndex]);
    				}
    			}
    			*/
    
    			GlobalMemoryStatus(&memstat);
    		} // for (int i=0; i<10; i++)
    
    		QueryPerformanceCounter(&end);
    
    		GlobalMemoryStatus(&memstat);
    
    		printf("Time %.3f\n",
    		double(end.QuadPart-start.QuadPart)/double(freq.QuadPart));
    		CloseHandle(mapping);
    		delete[] mem;
    		GlobalMemoryStatus(&memstat);
    	} //if (mapping)
    
    	fclose(fLog);
    
    	return 0;
    }
    

    thanks in advance,
    George
    George2, Jan 25, 2008
    #1
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jason Collins
    Replies:
    3
    Views:
    6,015
    Jason Collins
    Feb 18, 2004
  2. Z D
    Replies:
    4
    Views:
    1,205
    Alvin Bruney [MVP]
    Feb 26, 2004
  3. The Eeediot
    Replies:
    3
    Views:
    2,230
    =?Utf-8?B?UnVsaW4gSG9uZw==?=
    Dec 22, 2004
  4. =?Utf-8?B?aGF6eg==?=
    Replies:
    2
    Views:
    555
    =?Utf-8?B?aGF6eg==?=
    Apr 11, 2005
  5. George2
    Replies:
    1
    Views:
    795
    Alf P. Steinbach
    Jan 31, 2008
Loading...

Share This Page