327 lines
8.6 KiB
C++
327 lines
8.6 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: tests/benchmarks/bench.cpp
|
|
// Purpose: Main file of the benchmarking suite
|
|
// Author: Vadim Zeitlin
|
|
// Created: 2008-07-19
|
|
// Copyright: (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ============================================================================
|
|
// declarations
|
|
// ============================================================================
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// headers
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#include "wx/app.h"
|
|
#include "wx/cmdline.h"
|
|
#include "wx/stopwatch.h"
|
|
|
|
#if wxUSE_GUI
|
|
#include "wx/frame.h"
|
|
#endif
|
|
|
|
#include "bench.h"
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// constants
|
|
// ----------------------------------------------------------------------------
|
|
|
|
static const char OPTION_LIST = 'l';
|
|
static const char OPTION_SINGLE = '1';
|
|
|
|
static const char OPTION_AVG_COUNT = 'a';
|
|
static const char OPTION_NUM_RUNS = 'n';
|
|
static const char OPTION_NUMERIC_PARAM = 'p';
|
|
static const char OPTION_STRING_PARAM = 's';
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// BenchApp declaration
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#if wxUSE_GUI
|
|
typedef wxApp BenchAppBase;
|
|
#else
|
|
typedef wxAppConsole BenchAppBase;
|
|
#endif
|
|
|
|
class BenchApp : public BenchAppBase
|
|
{
|
|
public:
|
|
BenchApp();
|
|
|
|
// standard overrides
|
|
virtual void OnInitCmdLine(wxCmdLineParser& parser);
|
|
virtual bool OnCmdLineParsed(wxCmdLineParser& parser);
|
|
virtual bool OnInit();
|
|
virtual int OnRun();
|
|
virtual int OnExit();
|
|
|
|
// accessors
|
|
int GetNumericParameter() const { return m_numParam; }
|
|
const wxString& GetStringParameter() const { return m_strParam; }
|
|
|
|
private:
|
|
// list all registered benchmarks
|
|
void ListBenchmarks();
|
|
|
|
// command lines options/parameters
|
|
wxSortedArrayString m_toRun;
|
|
long m_numRuns,
|
|
m_avgCount,
|
|
m_numParam;
|
|
wxString m_strParam;
|
|
};
|
|
|
|
IMPLEMENT_APP_CONSOLE(BenchApp)
|
|
|
|
// ============================================================================
|
|
// Bench namespace symbols implementation
|
|
// ============================================================================
|
|
|
|
Bench::Function *Bench::Function::ms_head = NULL;
|
|
|
|
long Bench::GetNumericParameter()
|
|
{
|
|
return wxGetApp().GetNumericParameter();
|
|
}
|
|
|
|
wxString Bench::GetStringParameter()
|
|
{
|
|
return wxGetApp().GetStringParameter();
|
|
}
|
|
|
|
// ============================================================================
|
|
// BenchApp implementation
|
|
// ============================================================================
|
|
|
|
BenchApp::BenchApp()
|
|
{
|
|
m_avgCount = 10;
|
|
m_numRuns = 10000; // just some default (TODO: switch to time-based one)
|
|
m_numParam = 0;
|
|
}
|
|
|
|
bool BenchApp::OnInit()
|
|
{
|
|
if ( !BenchAppBase::OnInit() )
|
|
return false;
|
|
|
|
wxPrintf("wxWidgets benchmarking program\n"
|
|
"Build: %s\n", WX_BUILD_OPTIONS_SIGNATURE);
|
|
|
|
#if wxUSE_GUI
|
|
// create a hidden parent window to be used as parent for the GUI controls
|
|
new wxFrame(NULL, wxID_ANY, "Hidden wx benchmark frame");
|
|
#endif // wxUSE_GUI
|
|
|
|
return true;
|
|
}
|
|
|
|
void BenchApp::OnInitCmdLine(wxCmdLineParser& parser)
|
|
{
|
|
BenchAppBase::OnInitCmdLine(parser);
|
|
|
|
parser.AddSwitch(OPTION_LIST,
|
|
"list",
|
|
"list all the existing benchmarks");
|
|
|
|
parser.AddSwitch(OPTION_SINGLE,
|
|
"single",
|
|
"run the benchmark once only");
|
|
|
|
parser.AddOption(OPTION_AVG_COUNT,
|
|
"avg-count",
|
|
wxString::Format
|
|
(
|
|
"number of times to run benchmarking loop (default: %ld)",
|
|
m_avgCount
|
|
),
|
|
wxCMD_LINE_VAL_NUMBER);
|
|
parser.AddOption(OPTION_NUM_RUNS,
|
|
"num-runs",
|
|
wxString::Format
|
|
(
|
|
"number of times to run each benchmark in a loop "
|
|
"(default: %ld)",
|
|
m_numRuns
|
|
),
|
|
wxCMD_LINE_VAL_NUMBER);
|
|
parser.AddOption(OPTION_NUMERIC_PARAM,
|
|
"num-param",
|
|
wxString::Format
|
|
(
|
|
"numeric parameter used by some benchmark functions "
|
|
"(default: %ld)",
|
|
m_numParam
|
|
),
|
|
wxCMD_LINE_VAL_NUMBER);
|
|
parser.AddOption(OPTION_STRING_PARAM,
|
|
"str-param",
|
|
"string parameter used by some benchmark functions "
|
|
"(default: empty)",
|
|
wxCMD_LINE_VAL_STRING);
|
|
|
|
parser.AddParam("benchmark name",
|
|
wxCMD_LINE_VAL_STRING,
|
|
wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_PARAM_MULTIPLE);
|
|
}
|
|
|
|
bool BenchApp::OnCmdLineParsed(wxCmdLineParser& parser)
|
|
{
|
|
if ( parser.Found(OPTION_LIST) )
|
|
{
|
|
ListBenchmarks();
|
|
|
|
return false;
|
|
}
|
|
|
|
const size_t count = parser.GetParamCount();
|
|
if ( !count )
|
|
{
|
|
parser.Usage();
|
|
|
|
ListBenchmarks();
|
|
|
|
return false;
|
|
}
|
|
|
|
bool numRunsSpecified = false;
|
|
if ( parser.Found(OPTION_AVG_COUNT, &m_avgCount) )
|
|
numRunsSpecified = true;
|
|
if ( parser.Found(OPTION_NUM_RUNS, &m_numRuns) )
|
|
numRunsSpecified = true;
|
|
parser.Found(OPTION_NUMERIC_PARAM, &m_numParam);
|
|
parser.Found(OPTION_STRING_PARAM, &m_strParam);
|
|
if ( parser.Found(OPTION_SINGLE) )
|
|
{
|
|
if ( numRunsSpecified )
|
|
{
|
|
wxFprintf(stderr, "Incompatible options specified.\n");
|
|
|
|
return false;
|
|
}
|
|
|
|
m_avgCount =
|
|
m_numRuns = 1;
|
|
}
|
|
|
|
// construct sorted array for quick verification of benchmark names
|
|
wxSortedArrayString benchmarks;
|
|
for ( Bench::Function *func = Bench::Function::GetFirst();
|
|
func;
|
|
func = func->GetNext() )
|
|
{
|
|
benchmarks.push_back(func->GetName());
|
|
}
|
|
|
|
for ( size_t n = 0; n < count; n++ )
|
|
{
|
|
const wxString name = parser.GetParam(n);
|
|
if ( benchmarks.Index(name) == wxNOT_FOUND )
|
|
{
|
|
wxFprintf(stderr, "No benchmark named \"%s\".\n", name);
|
|
return false;
|
|
}
|
|
|
|
m_toRun.push_back(name);
|
|
}
|
|
|
|
return BenchAppBase::OnCmdLineParsed(parser);
|
|
}
|
|
|
|
int BenchApp::OnRun()
|
|
{
|
|
int rc = EXIT_SUCCESS;
|
|
for ( Bench::Function *func = Bench::Function::GetFirst();
|
|
func;
|
|
func = func->GetNext() )
|
|
{
|
|
if ( m_toRun.Index(func->GetName()) == wxNOT_FOUND )
|
|
continue;
|
|
|
|
wxString params;
|
|
if ( m_numParam )
|
|
params += wxString::Format(" with N=%ld", m_numParam);
|
|
if ( !m_strParam.empty() )
|
|
{
|
|
if ( !params.empty() )
|
|
params += " and";
|
|
params += wxString::Format(" with s=\"%s\"", m_strParam);
|
|
}
|
|
|
|
wxPrintf("Benchmarking %s%s: ", func->GetName(), params);
|
|
|
|
long timeMin = LONG_MAX,
|
|
timeMax = 0,
|
|
timeTotal = 0;
|
|
bool ok = func->Init();
|
|
for ( long a = 0; ok && a < m_avgCount; a++ )
|
|
{
|
|
wxStopWatch sw;
|
|
for ( long n = 0; n < m_numRuns && ok; n++ )
|
|
{
|
|
ok = func->Run();
|
|
}
|
|
|
|
sw.Pause();
|
|
|
|
const long t = sw.Time();
|
|
if ( t < timeMin )
|
|
timeMin = t;
|
|
if ( t > timeMax )
|
|
timeMax = t;
|
|
timeTotal += t;
|
|
}
|
|
|
|
func->Done();
|
|
|
|
if ( !ok )
|
|
{
|
|
wxPrintf("ERROR\n");
|
|
rc = EXIT_FAILURE;
|
|
}
|
|
else
|
|
{
|
|
wxPrintf("%ldms total, ", timeTotal);
|
|
|
|
long times = m_avgCount;
|
|
if ( m_avgCount > 2 )
|
|
{
|
|
timeTotal -= timeMin + timeMax;
|
|
times -= 2;
|
|
}
|
|
|
|
wxPrintf("%.2f avg (min=%ld, max=%ld)\n",
|
|
(float)timeTotal / times, timeMin, timeMax);
|
|
}
|
|
|
|
fflush(stdout);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
int BenchApp::OnExit()
|
|
{
|
|
#if wxUSE_GUI
|
|
delete GetTopWindow();
|
|
#endif // wxUSE_GUI
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* static */
|
|
void BenchApp::ListBenchmarks()
|
|
{
|
|
wxPrintf("Available benchmarks:\n");
|
|
for ( Bench::Function *func = Bench::Function::GetFirst();
|
|
func;
|
|
func = func->GetNext() )
|
|
{
|
|
wxPrintf("\t%s\n", func->GetName());
|
|
}
|
|
}
|