]> git.saurik.com Git - wxWidgets.git/blobdiff - tests/benchmarks/bench.cpp
added a simple benchmarking suite
[wxWidgets.git] / tests / benchmarks / bench.cpp
diff --git a/tests/benchmarks/bench.cpp b/tests/benchmarks/bench.cpp
new file mode 100644 (file)
index 0000000..ea9f5c9
--- /dev/null
@@ -0,0 +1,247 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        tests/benchmarks/bench.cpp
+// Purpose:     Main file of the benchmarking suite
+// Author:      Vadim Zeitlin
+// Created:     2008-07-19
+// RCS-ID:      $Id$
+// Copyright:   (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
+// Licence:     wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+#include "wx/app.h"
+#include "wx/cmdline.h"
+#include "wx/stopwatch.h"
+
+#include "bench.h"
+
+// ----------------------------------------------------------------------------
+// constants
+// ----------------------------------------------------------------------------
+
+static const char OPTION_LIST = 'l';
+
+static const char OPTION_AVG_COUNT = 'a';
+static const char OPTION_NUM_RUNS = 'n';
+
+// ----------------------------------------------------------------------------
+// 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();
+
+private:
+    // list all registered benchmarks
+    void ListBenchmarks();
+
+    // command lines options/parameters
+    wxSortedArrayString m_toRun;
+    long m_numRuns,
+         m_avgCount;
+};
+
+// ============================================================================
+// Bench::Function implementation
+// ============================================================================
+
+Bench::Function *Bench::Function::ms_head = NULL;
+
+// ============================================================================
+// BenchApp implementation
+// ============================================================================
+
+IMPLEMENT_APP_CONSOLE(BenchApp)
+
+BenchApp::BenchApp()
+{
+    m_avgCount = 10;
+    m_numRuns = 10000; // just some default (TODO: switch to time-based one)
+}
+
+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.AddOption(OPTION_AVG_COUNT,
+                     "avg-count",
+                     "number of times to run benchmarking loop",
+                     wxCMD_LINE_VAL_NUMBER);
+    parser.AddOption(OPTION_NUM_RUNS,
+                     "num-runs",
+                     "number of times to run each benchmark in a loop",
+                     wxCMD_LINE_VAL_NUMBER);
+    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;
+    }
+
+    parser.Found(OPTION_AVG_COUNT, &m_avgCount);
+    parser.Found(OPTION_NUM_RUNS, &m_numRuns);
+
+    // 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;
+
+        wxPrintf("Benchmarking %s: ", func->GetName());
+
+        long timeMin = LONG_MAX,
+             timeMax = 0,
+             timeTotal = 0;
+        bool ok = true;
+        for ( long a = 0; a < m_avgCount; a++ )
+        {
+            wxStopWatch sw;
+            for ( long n = 0; n < m_numRuns && ok; n++ )
+            {
+                ok = func->Run();
+            }
+
+            sw.Pause();
+
+            if ( !ok )
+                break;
+
+            const long t = sw.Time();
+            if ( t < timeMin )
+                timeMin = t;
+            if ( t > timeMax )
+                timeMax = t;
+            timeTotal += t;
+        }
+
+        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);
+        }
+    }
+
+    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());
+    }
+}