windows-nt/Source/XPSP1/NT/admin/pchealth/helpctr/debug/perf.cpp
2020-09-26 16:20:57 +08:00

293 lines
8.3 KiB
C++

/******************************************************************************
Copyright (c) 2000 Microsoft Corporation
Module Name:
Perf.cpp
Abstract:
This file contains debugging stuff.
Revision History:
Davide Massarenti (dmassare) 01/17/2000
created
******************************************************************************/
#include "stdafx.h"
////////////////////////////////////////////////////////////////////////////////
#ifdef HSS_PERFORMANCEDUMP
#include <ProjectConstants.h>
#include <MPC_utils.h>
////////////////////////////////////////////////////////////////////////////////
class PerfLog
{
public:
MPC::string szText;
LARGE_INTEGER liTime;
DWORDLONG ullTotal;
};
typedef std::list< PerfLog > PerfResults;
typedef PerfResults::iterator PerfResultsIter;
typedef PerfResults::const_iterator PerfResultsIterConst;
////////////////////////////////////////////////////////////////////////////////
static PerfResults s_lst;
static LARGE_INTEGER s_liStartOfPerf;
static LARGE_INTEGER s_liAdjust;
static MPC::CComSafeAutoCriticalSection s_csec;
////////////////////////////////////////////////////////////////////////////////
#define DEBUG_PERF_EVENTS DEBUG_PERF_EVENTS_IN | DEBUG_PERF_EVENTS_OUT
static const MPC::StringToBitField s_arrMap[] =
{
{ L"BASIC" , DEBUG_PERF_BASIC , DEBUG_PERF_BASIC , -1 },
{ L"PROTOCOL" , DEBUG_PERF_PROTOCOL , DEBUG_PERF_PROTOCOL , -1 },
{ L"PROTOCOL_READ", DEBUG_PERF_PROTOCOL_READ, DEBUG_PERF_PROTOCOL_READ, -1 },
{ L"MARS" , DEBUG_PERF_MARS , DEBUG_PERF_MARS , -1 },
{ L"EVENTS_IN" , DEBUG_PERF_EVENTS_IN , DEBUG_PERF_EVENTS_IN , -1 },
{ L"EVENTS_OUT" , DEBUG_PERF_EVENTS_OUT , DEBUG_PERF_EVENTS_OUT , -1 },
{ L"EVENTS" , DEBUG_PERF_EVENTS , DEBUG_PERF_EVENTS , -1 },
{ L"PROXIES" , DEBUG_PERF_PROXIES , DEBUG_PERF_PROXIES , -1 },
{ L"QUERIES" , DEBUG_PERF_QUERIES , DEBUG_PERF_QUERIES , -1 },
{ L"CACHE_L1" , DEBUG_PERF_CACHE_L1 , DEBUG_PERF_CACHE_L1 , -1 },
{ L"CACHE_L2" , DEBUG_PERF_CACHE_L2 , DEBUG_PERF_CACHE_L2 , -1 },
{ L"HELPSVC" , DEBUG_PERF_HELPSVC , DEBUG_PERF_HELPSVC , -1 },
{ L"HELPHOST" , DEBUG_PERF_HELPHOST , DEBUG_PERF_HELPHOST , -1 },
{ L"ALL" , -1 , -1 , -1 },
{ NULL }
};
static const WCHAR s_Key [] = HC_REGISTRY_BASE L"\\Perf";
static const WCHAR s_Value[] = L"Mask";
////////////////////////////////////////////////////////////////////////////////
static DWORD s_mode;
static LARGE_INTEGER s_liEnter;
static LARGE_INTEGER s_liExit;
static CHAR s_rgLineA[4096];
static WCHAR s_rgLineW[4096];
static void StopCounter()
{
s_csec.Lock();
::QueryPerformanceCounter( &s_liEnter );
if(s_liStartOfPerf.QuadPart == 0)
{
bool fFound;
s_liStartOfPerf = s_liEnter;
s_mode = DEBUG_PERF_BASIC;
if(FAILED(MPC::RegKey_Value_Read( s_mode, fFound, s_Key, s_Value )) || fFound == false)
{
MPC::wstring szValue;
if(SUCCEEDED(MPC::RegKey_Value_Read( szValue, fFound, s_Key, s_Value )) && fFound)
{
DWORD dwMode;
if(SUCCEEDED(MPC::ConvertStringToBitField( szValue.c_str(), dwMode, s_arrMap, true )) && dwMode)
{
s_mode = dwMode;
}
}
}
}
}
static void RestartCounter()
{
::QueryPerformanceCounter( &s_liExit );
s_liAdjust.QuadPart += s_liExit.QuadPart - s_liEnter.QuadPart;
s_csec.Unlock();
}
static void DEBUG_AppendPerf( LPCSTR szMessage )
{
PerfResultsIter it;
DWORDLONG ullTotal = 0;
{
HANDLE pHeaps[256];
DWORD dwNumberOfHeaps = ::GetProcessHeaps( ARRAYSIZE(pHeaps), pHeaps );
for(DWORD i=0; i<dwNumberOfHeaps; i++)
{
PROCESS_HEAP_ENTRY entry; entry.lpData = NULL;
while(::HeapWalk( pHeaps[i], &entry ))
{
if(entry.wFlags & PROCESS_HEAP_ENTRY_BUSY)
{
//
// Allocated block. Add both it's size and its overhead to the total
// We want the overhead since it figures into the total required
// commitment.
//
ullTotal += (entry.cbData + entry.cbOverhead);
}
}
}
}
it = s_lst.insert( s_lst.end() );
it->szText = szMessage;
it->liTime.QuadPart = s_liEnter.QuadPart - s_liStartOfPerf.QuadPart - s_liAdjust.QuadPart;
it->ullTotal = ullTotal;
}
void DEBUG_AppendPerf( DWORD mode ,
LPCSTR szMessageFmt ,
... )
{
StopCounter();
if(mode & s_mode)
{
va_list arglist;
int iLen;
//
// Format the log line.
//
va_start( arglist, szMessageFmt );
iLen = _vsnprintf( s_rgLineA, MAXSTRLEN(s_rgLineA), szMessageFmt, arglist );
va_end( arglist );
//
// Is the arglist too big for us?
//
if(iLen < 0)
{
iLen = MAXSTRLEN(s_rgLineA);
}
s_rgLineA[iLen] = 0;
DEBUG_AppendPerf( s_rgLineA );
}
RestartCounter();
}
void DEBUG_AppendPerf( DWORD mode ,
LPCWSTR szMessageFmt ,
... )
{
StopCounter();
if(mode & s_mode)
{
USES_CONVERSION;
va_list arglist;
int iLen;
//
// Format the log line.
//
va_start( arglist, szMessageFmt );
iLen = _vsnwprintf( s_rgLineW, MAXSTRLEN(s_rgLineW), szMessageFmt, arglist );
va_end( arglist );
//
// Is the arglist too big for us?
//
if(iLen < 0)
{
iLen = MAXSTRLEN(s_rgLineW);
}
s_rgLineW[iLen] = 0;
DEBUG_AppendPerf( W2A(s_rgLineW) );
}
RestartCounter();
}
void DEBUG_DumpPerf( LPCWSTR szFile )
{
HANDLE hFile;
SYSTEMTIME st;
DWORD dwWritten;
LARGE_INTEGER liFreq;
LARGE_INTEGER* pliPrev = NULL;
MPC::wstring strFile = szFile; MPC::SubstituteEnvVariables( strFile );
PerfResultsIter it;
int len;
double scale;
::QueryPerformanceFrequency( &liFreq ); scale = (double)liFreq.QuadPart / 1E6;
//
// Calc max entry length.
//
for(len=0,it=s_lst.begin(); it!=s_lst.end(); it++)
{
if(len < it->szText.size())
{
len = it->szText.size();
}
}
hFile = ::CreateFileW( strFile.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN, NULL );
if(hFile == INVALID_HANDLE_VALUE) goto end;
::SetFilePointer( hFile, 0, NULL, FILE_END );
//
// Prepend current time.
//
::GetLocalTime( &st );
sprintf( s_rgLineA, "Performance Dump: %04u/%02u/%02u %02u:%02u:%02u\n", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond );
if(::WriteFile( hFile, s_rgLineA, strlen( s_rgLineA ), &dwWritten, NULL ) == FALSE) goto end;
sprintf( s_rgLineA, "=====================================\n" );
if(::WriteFile( hFile, s_rgLineA, strlen( s_rgLineA ), &dwWritten, NULL ) == FALSE) goto end;
//
// Dump all the entries.
//
for(it=s_lst.begin(); it!=s_lst.end(); )
{
PerfLog& pl = *it++;
double t0 = (double)pl. liTime.QuadPart ;
double dT = it != s_lst.end() ? ((double)it->liTime.QuadPart - t0) : 0;
sprintf( s_rgLineA, "%-*s : %9ld us dT: %9ld us (Mem: %9ld)\n", len, pl.szText.c_str(), (long)(t0 / scale), (long)(dT / scale), (long)pl.ullTotal );
if(::WriteFile( hFile, s_rgLineA, strlen( s_rgLineA ), &dwWritten, NULL ) == FALSE) goto end;
}
sprintf( s_rgLineA, "\n\n\n" );
if(::WriteFile( hFile, s_rgLineA, strlen( s_rgLineA ), &dwWritten, NULL ) == FALSE) goto end;
end:
if(hFile != INVALID_HANDLE_VALUE) ::CloseHandle( hFile );
}
#endif