show default values of the options in the usage message
[wxWidgets.git] / tests / benchmarks / bench.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: tests/benchmarks/bench.cpp
3 // Purpose: Main file of the benchmarking suite
4 // Author: Vadim Zeitlin
5 // Created: 2008-07-19
6 // RCS-ID: $Id$
7 // Copyright: (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
8 // Licence: wxWindows license
9 /////////////////////////////////////////////////////////////////////////////
10
11 // ============================================================================
12 // declarations
13 // ============================================================================
14
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18
19 #include "wx/app.h"
20 #include "wx/cmdline.h"
21 #include "wx/stopwatch.h"
22
23 #include "bench.h"
24
25 // ----------------------------------------------------------------------------
26 // constants
27 // ----------------------------------------------------------------------------
28
29 static const char OPTION_LIST = 'l';
30
31 static const char OPTION_AVG_COUNT = 'a';
32 static const char OPTION_NUM_RUNS = 'n';
33
34 // ----------------------------------------------------------------------------
35 // BenchApp declaration
36 // ----------------------------------------------------------------------------
37
38 #if wxUSE_GUI
39 typedef wxApp BenchAppBase;
40 #else
41 typedef wxAppConsole BenchAppBase;
42 #endif
43
44 class BenchApp : public BenchAppBase
45 {
46 public:
47 BenchApp();
48
49 // standard overrides
50 virtual void OnInitCmdLine(wxCmdLineParser& parser);
51 virtual bool OnCmdLineParsed(wxCmdLineParser& parser);
52 virtual bool OnInit();
53 virtual int OnRun();
54 virtual int OnExit();
55
56 private:
57 // list all registered benchmarks
58 void ListBenchmarks();
59
60 // command lines options/parameters
61 wxSortedArrayString m_toRun;
62 long m_numRuns,
63 m_avgCount;
64 };
65
66 // ============================================================================
67 // Bench::Function implementation
68 // ============================================================================
69
70 Bench::Function *Bench::Function::ms_head = NULL;
71
72 // ============================================================================
73 // BenchApp implementation
74 // ============================================================================
75
76 IMPLEMENT_APP_CONSOLE(BenchApp)
77
78 BenchApp::BenchApp()
79 {
80 m_avgCount = 10;
81 m_numRuns = 10000; // just some default (TODO: switch to time-based one)
82 }
83
84 bool BenchApp::OnInit()
85 {
86 if ( !BenchAppBase::OnInit() )
87 return false;
88
89 wxPrintf("wxWidgets benchmarking program\n"
90 "Build: %s\n", WX_BUILD_OPTIONS_SIGNATURE);
91
92 #if wxUSE_GUI
93 // create a hidden parent window to be used as parent for the GUI controls
94 new wxFrame(NULL, wxID_ANY, "Hidden wx benchmark frame");
95 #endif // wxUSE_GUI
96
97 return true;
98 }
99
100 void BenchApp::OnInitCmdLine(wxCmdLineParser& parser)
101 {
102 BenchAppBase::OnInitCmdLine(parser);
103
104 parser.AddSwitch(OPTION_LIST,
105 "list",
106 "list all the existing benchmarks");
107
108 parser.AddOption(OPTION_AVG_COUNT,
109 "avg-count",
110 wxString::Format
111 (
112 "number of times to run benchmarking loop (default: %ld)",
113 m_avgCount
114 ),
115 wxCMD_LINE_VAL_NUMBER);
116 parser.AddOption(OPTION_NUM_RUNS,
117 "num-runs",
118 wxString::Format
119 (
120 "number of times to run each benchmark in a loop "
121 "(default: %ld)",
122 m_numRuns
123 ),
124 wxCMD_LINE_VAL_NUMBER);
125 parser.AddParam("benchmark name",
126 wxCMD_LINE_VAL_STRING,
127 wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_PARAM_MULTIPLE);
128 }
129
130 bool BenchApp::OnCmdLineParsed(wxCmdLineParser& parser)
131 {
132 if ( parser.Found(OPTION_LIST) )
133 {
134 ListBenchmarks();
135
136 return false;
137 }
138
139 const size_t count = parser.GetParamCount();
140 if ( !count )
141 {
142 parser.Usage();
143
144 ListBenchmarks();
145
146 return false;
147 }
148
149 parser.Found(OPTION_AVG_COUNT, &m_avgCount);
150 parser.Found(OPTION_NUM_RUNS, &m_numRuns);
151
152 // construct sorted array for quick verification of benchmark names
153 wxSortedArrayString benchmarks;
154 for ( Bench::Function *func = Bench::Function::GetFirst();
155 func;
156 func = func->GetNext() )
157 {
158 benchmarks.push_back(func->GetName());
159 }
160
161 for ( size_t n = 0; n < count; n++ )
162 {
163 const wxString name = parser.GetParam(n);
164 if ( benchmarks.Index(name) == wxNOT_FOUND )
165 {
166 wxFprintf(stderr, "No benchmark named \"%s\".\n", name);
167 return false;
168 }
169
170 m_toRun.push_back(name);
171 }
172
173 return BenchAppBase::OnCmdLineParsed(parser);
174 }
175
176 int BenchApp::OnRun()
177 {
178 int rc = EXIT_SUCCESS;
179 for ( Bench::Function *func = Bench::Function::GetFirst();
180 func;
181 func = func->GetNext() )
182 {
183 if ( m_toRun.Index(func->GetName()) == wxNOT_FOUND )
184 continue;
185
186 wxPrintf("Benchmarking %s: ", func->GetName());
187
188 long timeMin = LONG_MAX,
189 timeMax = 0,
190 timeTotal = 0;
191 bool ok = true;
192 for ( long a = 0; a < m_avgCount; a++ )
193 {
194 wxStopWatch sw;
195 for ( long n = 0; n < m_numRuns && ok; n++ )
196 {
197 ok = func->Run();
198 }
199
200 sw.Pause();
201
202 if ( !ok )
203 break;
204
205 const long t = sw.Time();
206 if ( t < timeMin )
207 timeMin = t;
208 if ( t > timeMax )
209 timeMax = t;
210 timeTotal += t;
211 }
212
213 if ( !ok )
214 {
215 wxPrintf("ERROR\n");
216 rc = EXIT_FAILURE;
217 }
218 else
219 {
220 wxPrintf("%ldms total, ", timeTotal);
221
222 long times = m_avgCount;
223 if ( m_avgCount > 2 )
224 {
225 timeTotal -= timeMin + timeMax;
226 times -= 2;
227 }
228
229 wxPrintf("%.2f avg (min=%ld, max=%ld)\n",
230 (float)timeTotal / times, timeMin, timeMax);
231 }
232 }
233
234 return rc;
235 }
236
237 int BenchApp::OnExit()
238 {
239 #if wxUSE_GUI
240 delete GetTopWindow();
241 #endif // wxUSE_GUI
242
243 return 0;
244 }
245
246 /* static */
247 void BenchApp::ListBenchmarks()
248 {
249 wxPrintf("Available benchmarks:\n");
250 for ( Bench::Function *func = Bench::Function::GetFirst();
251 func;
252 func = func->GetNext() )
253 {
254 wxPrintf("\t%s\n", func->GetName());
255 }
256 }