Change {DECLARE,IMPLEMENT}_*CLASS and {DECLARE,BEGIN,END}_EVENT_TABLE
occurrences to use the wx-prefixed version of the macros.
		
	
		
			
				
	
	
		
			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;
 | 
						|
};
 | 
						|
 | 
						|
wxIMPLEMENT_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());
 | 
						|
    }
 | 
						|
}
 |