Bug of performance counter API or perfmon tool

G

George2

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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top