blob: f77a455be8ae99577019545cbccd942ffeecd78f [file] [log] [blame]
/* **********************************************************
* Copyright (c) 2003 VMware, Inc. All rights reserved.
* **********************************************************/
/*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of VMware, Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
#define _WIN32_WINNT 0x0400
#include <Windows.h>
#include <stdio.h>
#include <Tlhelp32.h>
#include <tchar.h>
#include <pdh.h>
// a.s.
#include <stdlib.h>
#define MAXPATH 80
#define NCOUNTERS 27
#define MCOUNTERS 3
TCHAR *counters[NCOUNTERS] = {
_T("Thread Count"),
_T("Working Set"),
_T("Page Faults/sec"),
_T("Page File Bytes"),
_T("% User Time"),
_T("% Privileged Time"),
_T("% Processor Time"),
_T("Creating Process ID"),
_T("Elapsed Time"),
_T("Handle Count"),
_T("ID Process"),
_T("IO Data Bytes/sec"),
_T("IO Data Operations/sec"),
_T("IO Other Bytes/sec"),
_T("IO Other Operations/sec"),
_T("IO Read Bytes/sec"),
_T("IO Read Operations/sec"),
_T("IO Write Bytes/sec"),
_T("IO Write Operations/sec"),
_T("Page File Bytes Peak"),
_T("Pool Nonpaged Bytes"),
_T("Pool Paged Bytes"),
_T("Priority Base"),
_T("Private Bytes"),
_T("Virtual Bytes"),
_T("Virtual Bytes Peak"),
_T("Working Set Peak"),
};
TCHAR *shortnames[NCOUNTERS] = {
_T("tc"),
_T("wss"),
_T("pgflts"),
_T("pgfileK"),
_T("utimes"),
_T("ktimes"),
_T("ttimes"),
_T("ppid"),
_T("realtim"),
_T("handles"),
_T("pid"),
_T("IOdataK"),
_T("IOdataO"),
_T("IOothrK"),
_T("IOothrO"),
_T("IOreadK"),
_T("IOreadO"),
_T("IOwritK"),
_T("IOwritO"),
_T("pgfpeak"),
_T("poolnpK"),
_T("poolpK"),
_T("priorty"),
_T("privK"),
_T("vmK"),
_T("vmpeak"),
_T("wsspeak"),
};
TCHAR *formatstrings[NCOUNTERS] = {
_T("%.0f\t"),
_T("%.0f\t"),
_T("%.0f\t"),
_T("%.0f\t"),
_T("%.2f\t"),
_T("%.2f\t"),
_T("%.2f\t"),
_T("%.0f\t"),
_T("%.2f\t"),
_T("%.0f\t"),
_T("%.0f\t"),
_T("%.0f\t"),
_T("%.0f\t"),
_T("%.0f\t"),
_T("%.0f\t"),
_T("%.0f\t"),
_T("%.0f\t"),
_T("%.0f\t"),
_T("%.0f\t"),
_T("%.0f\t"),
_T("%.0f\t"),
_T("%.0f\t"),
_T("%.0f\t"),
_T("%.0f\t"),
_T("%.0f\t"),
_T("%.0f\t"),
_T("%.0f\t"),
};
BOOL use_kb[NCOUNTERS] = {
0,
1,
0,
1,
0,
0,
0,
0,
0,
0,
0,
1,
0,
1,
0,
1,
0,
1,
0,
1,
1,
1,
0,
1,
1,
1,
1,
};
int waitforprocess(TCHAR *name) {
HANDLE processes;
PROCESSENTRY32 pe = { sizeof(pe) };
BOOL fOK;
while(1) {
processes = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
fOK = Process32First(processes, &pe);
for (; fOK; fOK = Process32Next(processes, &pe)) {
if(!_tcsicmp(pe.szExeFile,name))
return pe.th32ProcessID;
}
CloseHandle(processes);
Sleep(181);
}
}
// a.s.
void GetProcNameFromId( int pid, TCHAR* pName )
{
HANDLE processes;
PROCESSENTRY32 pe = { sizeof(pe) };
BOOL fOK;
while(1) {
processes = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
fOK = Process32First(processes, &pe);
for (; fOK; fOK = Process32Next(processes, &pe)) {
if( (int)pe.th32ProcessID == pid)
{
_tcscpy( pName, pe.szExeFile );
return;
}
}
CloseHandle(processes);
Sleep(181);
}
}
// eof a.s.
int __cdecl _tmain (int argc, TCHAR **argv)
{
HQUERY hQuery;
HCOUNTER *pCounterHandle;
PDH_STATUS pdhStatus;
PDH_FMT_COUNTERVALUE fmtValue;
DWORD ctrType;
TCHAR szPathBuffer[MAXPATH];
int i, samples=0;
int NUM_SAMPLES=1000, INTERVAL_MS=1000;
int pid;
FILE *fp = stdout;
char fn[MAXPATH];
TCHAR basename[MAXPATH];
HANDLE htimer;
LARGE_INTEGER duetime;
if(argc<2) {
_ftprintf(stderr,_T("Usage: %s [<exeName> | <pid> | all] [num_samples] [interval] [outputfile]\n"), argv[0]);
return -1;
}
if(_tcscmp(argv[1],_T("all"))) {
if( isalpha( *argv[1] ) ) {
printf("waiting...\n");
pid = waitforprocess(argv[1]);
//remove .exe
_tcscpy(basename, argv[1]);
basename[_tcslen(argv[1]) - 4] = _T('\0');
}
else {
pid = _ttoi( argv[1] );
GetProcNameFromId( pid, basename );
basename[_tcslen(basename) - 4] = _T('\0');
}
// eof a.s.
}
else {
pid = 0;
_tcscpy(basename, _T("_Total"));
}
if(argc>2) {
NUM_SAMPLES=_ttoi(argv[2]);
if(argc>3)
INTERVAL_MS=_ttoi(argv[3]);
if(argc>4) {
sprintf(fn, "%S", argv[4]);
fp = fopen(fn,"w");
if(fp==NULL) {
_ftprintf(stderr, _T("error opening output file %s\n"),
argv[4]);
return -1;
}
}
}
_ftprintf(stderr,
_T("Monitoring %s, pid=%d. Using %d samples at %dms interval\n"),
basename, pid, NUM_SAMPLES, INTERVAL_MS);
pdhStatus = PdhOpenQuery (0, 0, &hQuery);
pCounterHandle = (HCOUNTER *)malloc(NCOUNTERS*sizeof(HCOUNTER));
for(i=0; i<NCOUNTERS; ++i) {
_stprintf(szPathBuffer,_T("\\Process(%s)\\%s"), basename, counters[i]);
pdhStatus = PdhAddCounter (hQuery,
szPathBuffer,
0,
&pCounterHandle[i]);
}
// "Prime" counters that need two values to display a formatted value.
pdhStatus = PdhCollectQueryData (hQuery);
//disp titles
for(i=0; i<NCOUNTERS; ++i)
_ftprintf(fp, _T("%s\t"), shortnames[i]);
_ftprintf(fp, _T("\n"));
htimer = CreateWaitableTimer(NULL, FALSE, NULL);
duetime.LowPart = 0;
duetime.HighPart = 0;
SetWaitableTimer(htimer, &duetime, INTERVAL_MS, NULL, NULL, FALSE);
while (samples++ < NUM_SAMPLES) {
//first wait is instantaneous
WaitForSingleObject(htimer, INTERVAL_MS * 2);
pdhStatus = PdhCollectQueryData (hQuery);
for(i=0; i<NCOUNTERS; ++i) {
// Get the current value of this counter.
pdhStatus = PdhGetFormattedCounterValue (pCounterHandle[i],
PDH_FMT_DOUBLE,
&ctrType,
&fmtValue);
if (pdhStatus == ERROR_SUCCESS) {
_ftprintf (fp, formatstrings[i], use_kb[i] ?
fmtValue.doubleValue / 1024 : fmtValue.doubleValue);
} else {
goto processgone;
}
}
_ftprintf(fp, _T("\n"));
}
processgone:
pdhStatus = PdhCloseQuery (hQuery);
if(fp != stdout)
fclose(fp);
free(pCounterHandle);
return 0;
}