windows-nt/Source/XPSP1/NT/shell/themes/test/ctlperf/perflog.cpp
2020-09-26 16:20:57 +08:00

588 lines
15 KiB
C++

//------------------------------------------------------------------------
//
// File: shell\themes\test\ctlperf\Perflog.cpp
//
// Contents: Implementation of the Timing and logging class.
//
// Classes: CPerfLog
//
//------------------------------------------------------------------------
#include "stdafx.h"
#include "PerfLog.h"
//+-----------------------------------------------------------------------
//
// Member: CPerfLog::CPerfLog
//
// Synopsis: Constructor
//
//------------------------------------------------------------------------
CPerfLog::CPerfLog()
{
::QueryPerformanceFrequency( (LARGE_INTEGER*) &m_liFreq);
m_szPass1[0] = _T('\0');
m_szPass2[0] = _T('\0');
m_bLogging = false;
m_nFramePaintTime = 0;
m_nFrameResizeTime = 0;
m_nFrameResizeAndPaintTime = 0;
m_bFrame = false;
m_bTwoPasses = false;
m_rgnResults1 = NULL;
m_rgnResults2 = NULL;
m_rgszResults = NULL;
m_cnResults1 = 0;
m_cnResults2 = 0;
m_cszResults = 0;
m_bFirstPass = true;
m_flLogFile = NULL;
m_bNumberOnly = false;
}
//+-----------------------------------------------------------------------
//
// Member: CPerfLog::~CPerfLog
//
// Synopsis: Destructor
//
//------------------------------------------------------------------------
CPerfLog::~CPerfLog()
{
StopLogging(); // Just in case the caller didn't call it
}
//+-----------------------------------------------------------------------
//
// Member: CPerfLog::StartLoggingOnePass
//
// Synopsis: Initialization method when loggin one pass
//
// Arguments: szFileName Name of the log file
// hWndStatusBar Handle to a status bar window to receive info
// szPass Name of the test
//
//------------------------------------------------------------------------
void CPerfLog::StartLoggingOnePass(LPCTSTR szFileName, HWND hWndStatusBar, LPCTSTR szPass)
{
if (m_bLogging)
{
StopLogging();
}
if (m_liFreq == 0) // We can't do anything without it
{
m_bLogging = false;
return;
}
if (szFileName)
{
_tcscpy(m_szFileName, szFileName);
}
if(szPass)
{
_tcscpy(m_szPass1, szPass);
}
m_flLogFile = ::_wfopen(szFileName, _T("w"));
ATLASSERT(m_flLogFile);
if(m_flLogFile != NULL)
{
m_hWndStatusBar = hWndStatusBar;
m_nFramePaintTime = 0;
m_nFrameResizeTime = 0;
m_nFrameResizeAndPaintTime = 0;
m_bLogging = true;
}
}
//+-----------------------------------------------------------------------
//
// Member: CPerfLog::StopLogging
//
// Synopsis: Close and cleanup
//
//------------------------------------------------------------------------
void CPerfLog::StopLogging()
{
if (m_flLogFile && ::ftell(m_flLogFile) != -1)
{
::fflush(m_flLogFile);
::fclose(m_flLogFile);
m_flLogFile = NULL;
}
if (m_rgnResults1)
{
free(m_rgnResults1);
m_rgnResults1 = NULL;
m_cnResults1 = 0;
}
if (m_rgnResults2)
{
free(m_rgnResults2);
m_rgnResults2 = NULL;
m_cnResults2 = 0;
}
if (m_cszResults)
{
for (UINT i = 0; i < m_cszResults; i++)
free(m_rgszResults[i]);
free(m_rgszResults);
m_rgszResults = NULL;
m_cszResults = 0;
}
m_bLogging = false;
}
//+-----------------------------------------------------------------------
//
// Member: CPerfLog::StartLoggingTwoPasses
//
// Synopsis: Initialization method when loggin two passes
//
// Arguments: szFileName Name of the log file
// hWndStatusBar Handle to a status bar window to receive info
// szPass1 Name of the first test
// szPass2 Name of the second test
//
//------------------------------------------------------------------------
void CPerfLog::StartLoggingTwoPasses(LPCTSTR szFileName, HWND hWndStatusBar, LPCTSTR szPass1, LPCTSTR szPass2)
{
m_bTwoPasses = true;
StartLoggingOnePass(szFileName, hWndStatusBar, NULL); // Reuse main initialization (dirty)
if (szPass1)
{
_tcscpy(m_szPass1, szPass1);
}
if (szPass2)
{
_tcscpy(m_szPass2, szPass2);
}
}
//+-----------------------------------------------------------------------
//
// Member: CPerfLog::StopLoggingPass1
//
// Synopsis: For parity, does nothing
//
//------------------------------------------------------------------------
void CPerfLog::StopLoggingPass1()
{
}
//+-----------------------------------------------------------------------
//
// Member: CPerfLog::StartLoggingPass2
//
// Synopsis: Log pass 2
//
//------------------------------------------------------------------------
void CPerfLog::StartLoggingPass2()
{
// Reset variables from pass 1
m_nFramePaintTime = 0;
m_nFrameResizeTime = 0;
m_nFrameResizeAndPaintTime = 0;
m_bFirstPass = false;
}
//+-----------------------------------------------------------------------
//
// Member: CPerfLog::StopLoggingPass2
//
// Synopsis: Close pass 2, output log and cleanup
//
//------------------------------------------------------------------------
void CPerfLog::StopLoggingPass2()
{
UINT iResults2 = 0;
UINT iszResults1 = 0;
for (UINT iResults1 = 0; iResults1 < m_cnResults1; iResults1++)
{
if (m_rgnResults1[iResults1] == -1) // This is a string
{
fputws(m_rgszResults[iszResults1++], m_flLogFile);
}
else // Two results to display on the same line
{
if (m_rgnResults1[iResults1])
{
// just remvoed one \t so that slow colum would line up.
swprintf(m_szBuf,
_T("%u\t\t%u\t%.2f\n"),
m_rgnResults1[iResults1],
m_rgnResults2[iResults2],
(100.0f * float(m_rgnResults2[iResults2]) / float(m_rgnResults1[iResults1])) - 100.0f);
}
else
{
swprintf(m_szBuf, _T("%u\t\t%u\t\t0\n"), m_rgnResults1[iResults1], m_rgnResults2[iResults2]);
}
iResults2++;
fputws(m_szBuf, m_flLogFile);
}
}
StopLogging();
}
//+-----------------------------------------------------------------------
//
// Member: CPerfLog::LogString
//
// Synopsis: Stores the string in memory
//
// Arguments: sz String to log
//
//------------------------------------------------------------------------
void CPerfLog::LogString(LPCTSTR sz)
{
if (!m_bTwoPasses)
{
fputws(sz, m_flLogFile);
}
else if (m_bFirstPass)
{
m_cszResults++;
m_rgszResults = (LPTSTR*) realloc(m_rgszResults, m_cszResults * sizeof(LPTSTR));
m_rgszResults[m_cszResults - 1] = _wcsdup(sz);
m_cnResults1++;
m_rgnResults1 = (UINT*) realloc(m_rgnResults1, m_cnResults1 * sizeof(UINT));
// Since -1 is an illegal value for the results, we use it to mark a string
m_rgnResults1[m_cnResults1 - 1] = -1;
}
}
//+-----------------------------------------------------------------------
//
// Member: CPerfLog::OpenLoggingClass
//
// Synopsis: Start timing a new control class name for the following timing
//
// Arguments: szClassName Name of class (for logging only)
//
//------------------------------------------------------------------------
void CPerfLog::OpenLoggingClass(LPCTSTR szClassName)
{
if (!m_bLogging)
{
return;
}
::SendMessage(m_hWndStatusBar, SB_SIMPLE, TRUE, 0L);
::SendMessage(m_hWndStatusBar, SB_SETTEXT, (255 | SBT_NOBORDERS), (LPARAM) szClassName);
// Class header in the file
if (m_bTwoPasses)
{
// added number only check
if(m_bNumberOnly)
{
swprintf(m_szBuf, _T("%.12s\t%s\t%% Slower\n"), m_szPass1, m_szPass2);
}
else
{
swprintf(m_szBuf, _T("%-23s\t%.12s\t%s\t%% Slower\n"), szClassName, m_szPass1, m_szPass2);
}
}
else
{
// added number only check
if(m_bNumberOnly)
{
swprintf(m_szBuf, _T("%-23s\n"), szClassName);
}
else
{
swprintf(m_szBuf, _T("%-23s\t%s\n"), szClassName, m_szPass1);
}
}
LogString(m_szBuf);
if (!m_bFrame && !_tcsicmp(szClassName, kszFrameWnd))
{
m_bFrame = true;
}
else
{
m_bFrame = false;
}
}
//+-----------------------------------------------------------------------
//
// Member: CPerfLog::CloseLoggingClass
//
// Synopsis: Finished with this class
//
//------------------------------------------------------------------------
void CPerfLog::CloseLoggingClass()
{
if (!m_bLogging)
{
return;
}
LogString(_T("\n"));
::SendMessage(m_hWndStatusBar, SB_SETTEXT, (255 | SBT_NOBORDERS), (LPARAM) _T(""));
}
//+-----------------------------------------------------------------------
//
// Member: CPerfLog::StartCreate
//
// Synopsis: Beginning timing creation test
//
// Arguments: cCtl Number of controls being created (for logging)
//
//------------------------------------------------------------------------
void CPerfLog::StartCreate(UINT cCtl)
{
if (!m_bLogging)
{
return;
}
// added number only check
if(!m_bNumberOnly)
{
swprintf(m_szBuf, _T("Creation(x%d)\t\t"), cCtl);
LogString(m_szBuf);
}
::QueryPerformanceCounter( (LARGE_INTEGER*) &m_liStart);
}
//+-----------------------------------------------------------------------
//
// Member: CPerfLog::StopCreate
//
// Synopsis: Finished timing creation test
//
//------------------------------------------------------------------------
void CPerfLog::StopCreate()
{
if (!m_bLogging)
{
return;
}
::QueryPerformanceCounter( (LARGE_INTEGER*) &m_liEnd);
OutputData();
}
//+-----------------------------------------------------------------------
//
// Member: CPerfLog::StartPaint
//
// Synopsis: Beginning timing painting test
//
// Arguments: nTimes Number of loops executed (for logging)
//
//------------------------------------------------------------------------
void CPerfLog::StartPaint(UINT nTimes)
{
if (!m_bLogging)
{
return;
}
// added number only check
if(!m_bNumberOnly)
{
swprintf(m_szBuf, _T("Paint(x%d)\t\t"), nTimes);
LogString(m_szBuf);
}
::QueryPerformanceCounter( (LARGE_INTEGER*) &m_liStart);
}
//+-----------------------------------------------------------------------
//
// Member: CPerfLog::StopPaint
//
// Synopsis: Finished timing painting test
//
//------------------------------------------------------------------------
void CPerfLog::StopPaint()
{
if (!m_bLogging)
{
return;
}
::QueryPerformanceCounter( (LARGE_INTEGER*) &m_liEnd);
if (m_nFramePaintTime > 0)
{
m_liEnd -= m_nFramePaintTime;
}
OutputData();
if (m_bFrame)
{
ATLASSERT(m_nFramePaintTime == 0);
m_nFramePaintTime = UINT(m_liEnd - m_liStart);
}
}
//+-----------------------------------------------------------------------
//
// Member: CPerfLog::StartResize
//
// Synopsis: Beginning timing resizing test
//
// Arguments: nTimes Number of loops executed (for logging)
//
//------------------------------------------------------------------------
void CPerfLog::StartResize(UINT nTimes)
{
if (!m_bLogging)
{
return;
}
// added number only check
if(!m_bNumberOnly)
{
swprintf(m_szBuf, _T("Resize(x%d)\t\t"), nTimes);
LogString(m_szBuf);
}
::QueryPerformanceCounter( (LARGE_INTEGER*) &m_liStart);
}
//+-----------------------------------------------------------------------
//
// Member: CPerfLog::StopResize
//
// Synopsis: Finished timing resizing test
//
//------------------------------------------------------------------------
void CPerfLog::StopResize()
{
if (!m_bLogging)
{
return;
}
::QueryPerformanceCounter( (LARGE_INTEGER*) &m_liEnd);
if (m_nFrameResizeTime > 0)
{
m_liEnd -= m_nFrameResizeTime;
}
OutputData();
if (m_bFrame)
{
ATLASSERT(m_nFrameResizeTime == 0);
m_nFrameResizeTime = UINT(m_liEnd - m_liStart);
}
}
//+-----------------------------------------------------------------------
//
// Member: CPerfLog::StartResizeAndPaint
//
// Synopsis: Beginning timing resizing with painting test
//
// Arguments: nTimes Number of loops executed (for logging)
//
//------------------------------------------------------------------------
void CPerfLog::StartResizeAndPaint(UINT nTimes)
{
if (!m_bLogging)
{
return;
}
// added number only check
if(!m_bNumberOnly)
{
swprintf(m_szBuf, _T("Resize and paint(x%d)\t"), nTimes);
LogString(m_szBuf);
}
::QueryPerformanceCounter( (LARGE_INTEGER*) &m_liStart);
}
//+-----------------------------------------------------------------------
//
// Member: CPerfLog::StopResizeAndPaint
//
// Synopsis: Finished timing resizing with painting test
//
//------------------------------------------------------------------------
void CPerfLog::StopResizeAndPaint()
{
if (!m_bLogging)
{
return;
}
::QueryPerformanceCounter( (LARGE_INTEGER*) &m_liEnd);
if (m_nFrameResizeAndPaintTime > 0)
{
m_liEnd -= m_nFrameResizeAndPaintTime;
}
OutputData();
if (m_bFrame)
{
ATLASSERT(m_nFrameResizeAndPaintTime == 0);
m_nFrameResizeAndPaintTime = UINT(m_liEnd - m_liStart);
}
}
//+-----------------------------------------------------------------------
//
// Member: CPerfLog::OutputData
//
// Synopsis: Stores the data in one of the buffers
//
//------------------------------------------------------------------------
void CPerfLog::OutputData()
{
if (m_liEnd < m_liStart) // In case nLoops is low, it can happen
{
m_liEnd = m_liStart;
}
UINT nData = UINT((1000.0 * double(m_liEnd - m_liStart)) / double(m_liFreq));
if (!m_bTwoPasses)
{
fwprintf(m_flLogFile, _T("%u\n"), nData);
}
else
{
if (m_bFirstPass)
{
m_cnResults1++;
m_rgnResults1 = (UINT*) realloc(m_rgnResults1, m_cnResults1 * sizeof(UINT));
m_rgnResults1[m_cnResults1 - 1] = nData;
}
else
{
m_cnResults2++;
m_rgnResults2 = (UINT*) realloc(m_rgnResults2, m_cnResults2 * sizeof(UINT));
m_rgnResults2[m_cnResults2 - 1] = nData;
}
}
}
//+-----------------------------------------------------------------------
//
// Member: CPerfLog::SetOutputType
//
// Synopsis: Stores the output type (numbers only) for use later
//
//------------------------------------------------------------------------
void CPerfLog::SetOutputType(LPTSTR szNumberOnly)
{
if(!_tcsicmp(szNumberOnly, _T("true")))
{
m_bNumberOnly = true;
}
}