]>
Commit | Line | Data |
---|---|---|
dc2ae355 VZ |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: tests/benchmarks/bench.cpp | |
3 | // Purpose: Main file of the benchmarking suite | |
4 | // Author: Vadim Zeitlin | |
5 | // Created: 2008-07-19 | |
dc2ae355 | 6 | // Copyright: (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org> |
526954c5 | 7 | // Licence: wxWindows licence |
dc2ae355 VZ |
8 | ///////////////////////////////////////////////////////////////////////////// |
9 | ||
10 | // ============================================================================ | |
11 | // declarations | |
12 | // ============================================================================ | |
13 | ||
14 | // ---------------------------------------------------------------------------- | |
15 | // headers | |
16 | // ---------------------------------------------------------------------------- | |
17 | ||
18 | #include "wx/app.h" | |
19 | #include "wx/cmdline.h" | |
20 | #include "wx/stopwatch.h" | |
21 | ||
7b363ab6 VZ |
22 | #if wxUSE_GUI |
23 | #include "wx/frame.h" | |
24 | #endif | |
25 | ||
dc2ae355 VZ |
26 | #include "bench.h" |
27 | ||
28 | // ---------------------------------------------------------------------------- | |
29 | // constants | |
30 | // ---------------------------------------------------------------------------- | |
31 | ||
32 | static const char OPTION_LIST = 'l'; | |
139ea30e | 33 | static const char OPTION_SINGLE = '1'; |
dc2ae355 VZ |
34 | |
35 | static const char OPTION_AVG_COUNT = 'a'; | |
36 | static const char OPTION_NUM_RUNS = 'n'; | |
8fad8b2e | 37 | static const char OPTION_NUMERIC_PARAM = 'p'; |
ebfa7cea | 38 | static const char OPTION_STRING_PARAM = 's'; |
dc2ae355 VZ |
39 | |
40 | // ---------------------------------------------------------------------------- | |
41 | // BenchApp declaration | |
42 | // ---------------------------------------------------------------------------- | |
43 | ||
44 | #if wxUSE_GUI | |
45 | typedef wxApp BenchAppBase; | |
46 | #else | |
47 | typedef wxAppConsole BenchAppBase; | |
48 | #endif | |
49 | ||
50 | class BenchApp : public BenchAppBase | |
51 | { | |
52 | public: | |
53 | BenchApp(); | |
54 | ||
55 | // standard overrides | |
56 | virtual void OnInitCmdLine(wxCmdLineParser& parser); | |
57 | virtual bool OnCmdLineParsed(wxCmdLineParser& parser); | |
58 | virtual bool OnInit(); | |
59 | virtual int OnRun(); | |
60 | virtual int OnExit(); | |
61 | ||
ebfa7cea | 62 | // accessors |
8fad8b2e | 63 | int GetNumericParameter() const { return m_numParam; } |
ebfa7cea | 64 | const wxString& GetStringParameter() const { return m_strParam; } |
8fad8b2e | 65 | |
dc2ae355 VZ |
66 | private: |
67 | // list all registered benchmarks | |
68 | void ListBenchmarks(); | |
69 | ||
70 | // command lines options/parameters | |
71 | wxSortedArrayString m_toRun; | |
72 | long m_numRuns, | |
8fad8b2e VZ |
73 | m_avgCount, |
74 | m_numParam; | |
ebfa7cea | 75 | wxString m_strParam; |
dc2ae355 VZ |
76 | }; |
77 | ||
8fad8b2e VZ |
78 | IMPLEMENT_APP_CONSOLE(BenchApp) |
79 | ||
dc2ae355 | 80 | // ============================================================================ |
8fad8b2e | 81 | // Bench namespace symbols implementation |
dc2ae355 VZ |
82 | // ============================================================================ |
83 | ||
84 | Bench::Function *Bench::Function::ms_head = NULL; | |
85 | ||
8fad8b2e VZ |
86 | long Bench::GetNumericParameter() |
87 | { | |
88 | return wxGetApp().GetNumericParameter(); | |
89 | } | |
90 | ||
ebfa7cea VZ |
91 | wxString Bench::GetStringParameter() |
92 | { | |
93 | return wxGetApp().GetStringParameter(); | |
94 | } | |
95 | ||
dc2ae355 VZ |
96 | // ============================================================================ |
97 | // BenchApp implementation | |
98 | // ============================================================================ | |
99 | ||
dc2ae355 VZ |
100 | BenchApp::BenchApp() |
101 | { | |
102 | m_avgCount = 10; | |
103 | m_numRuns = 10000; // just some default (TODO: switch to time-based one) | |
ebfa7cea | 104 | m_numParam = 0; |
dc2ae355 VZ |
105 | } |
106 | ||
107 | bool BenchApp::OnInit() | |
108 | { | |
109 | if ( !BenchAppBase::OnInit() ) | |
110 | return false; | |
111 | ||
112 | wxPrintf("wxWidgets benchmarking program\n" | |
113 | "Build: %s\n", WX_BUILD_OPTIONS_SIGNATURE); | |
114 | ||
115 | #if wxUSE_GUI | |
116 | // create a hidden parent window to be used as parent for the GUI controls | |
117 | new wxFrame(NULL, wxID_ANY, "Hidden wx benchmark frame"); | |
118 | #endif // wxUSE_GUI | |
119 | ||
120 | return true; | |
121 | } | |
122 | ||
123 | void BenchApp::OnInitCmdLine(wxCmdLineParser& parser) | |
124 | { | |
125 | BenchAppBase::OnInitCmdLine(parser); | |
126 | ||
127 | parser.AddSwitch(OPTION_LIST, | |
128 | "list", | |
129 | "list all the existing benchmarks"); | |
130 | ||
139ea30e VZ |
131 | parser.AddSwitch(OPTION_SINGLE, |
132 | "single", | |
133 | "run the benchmark once only"); | |
134 | ||
dc2ae355 VZ |
135 | parser.AddOption(OPTION_AVG_COUNT, |
136 | "avg-count", | |
c517ecec VZ |
137 | wxString::Format |
138 | ( | |
139 | "number of times to run benchmarking loop (default: %ld)", | |
140 | m_avgCount | |
141 | ), | |
dc2ae355 VZ |
142 | wxCMD_LINE_VAL_NUMBER); |
143 | parser.AddOption(OPTION_NUM_RUNS, | |
144 | "num-runs", | |
c517ecec VZ |
145 | wxString::Format |
146 | ( | |
147 | "number of times to run each benchmark in a loop " | |
148 | "(default: %ld)", | |
149 | m_numRuns | |
150 | ), | |
dc2ae355 | 151 | wxCMD_LINE_VAL_NUMBER); |
8fad8b2e VZ |
152 | parser.AddOption(OPTION_NUMERIC_PARAM, |
153 | "num-param", | |
ebfa7cea VZ |
154 | wxString::Format |
155 | ( | |
156 | "numeric parameter used by some benchmark functions " | |
157 | "(default: %ld)", | |
158 | m_numParam | |
159 | ), | |
8fad8b2e | 160 | wxCMD_LINE_VAL_NUMBER); |
ebfa7cea VZ |
161 | parser.AddOption(OPTION_STRING_PARAM, |
162 | "str-param", | |
163 | "string parameter used by some benchmark functions " | |
164 | "(default: empty)", | |
165 | wxCMD_LINE_VAL_STRING); | |
8fad8b2e | 166 | |
dc2ae355 VZ |
167 | parser.AddParam("benchmark name", |
168 | wxCMD_LINE_VAL_STRING, | |
169 | wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_PARAM_MULTIPLE); | |
170 | } | |
171 | ||
172 | bool BenchApp::OnCmdLineParsed(wxCmdLineParser& parser) | |
173 | { | |
174 | if ( parser.Found(OPTION_LIST) ) | |
175 | { | |
176 | ListBenchmarks(); | |
177 | ||
178 | return false; | |
179 | } | |
180 | ||
181 | const size_t count = parser.GetParamCount(); | |
182 | if ( !count ) | |
183 | { | |
184 | parser.Usage(); | |
185 | ||
186 | ListBenchmarks(); | |
187 | ||
188 | return false; | |
189 | } | |
190 | ||
139ea30e VZ |
191 | bool numRunsSpecified = false; |
192 | if ( parser.Found(OPTION_AVG_COUNT, &m_avgCount) ) | |
193 | numRunsSpecified = true; | |
194 | if ( parser.Found(OPTION_NUM_RUNS, &m_numRuns) ) | |
195 | numRunsSpecified = true; | |
8fad8b2e | 196 | parser.Found(OPTION_NUMERIC_PARAM, &m_numParam); |
ebfa7cea | 197 | parser.Found(OPTION_STRING_PARAM, &m_strParam); |
139ea30e VZ |
198 | if ( parser.Found(OPTION_SINGLE) ) |
199 | { | |
200 | if ( numRunsSpecified ) | |
201 | { | |
202 | wxFprintf(stderr, "Incompatible options specified.\n"); | |
203 | ||
204 | return false; | |
205 | } | |
206 | ||
207 | m_avgCount = | |
208 | m_numRuns = 1; | |
209 | } | |
dc2ae355 VZ |
210 | |
211 | // construct sorted array for quick verification of benchmark names | |
212 | wxSortedArrayString benchmarks; | |
213 | for ( Bench::Function *func = Bench::Function::GetFirst(); | |
214 | func; | |
215 | func = func->GetNext() ) | |
216 | { | |
217 | benchmarks.push_back(func->GetName()); | |
218 | } | |
219 | ||
220 | for ( size_t n = 0; n < count; n++ ) | |
221 | { | |
222 | const wxString name = parser.GetParam(n); | |
223 | if ( benchmarks.Index(name) == wxNOT_FOUND ) | |
224 | { | |
225 | wxFprintf(stderr, "No benchmark named \"%s\".\n", name); | |
226 | return false; | |
227 | } | |
228 | ||
229 | m_toRun.push_back(name); | |
230 | } | |
231 | ||
232 | return BenchAppBase::OnCmdLineParsed(parser); | |
233 | } | |
234 | ||
235 | int BenchApp::OnRun() | |
236 | { | |
237 | int rc = EXIT_SUCCESS; | |
238 | for ( Bench::Function *func = Bench::Function::GetFirst(); | |
239 | func; | |
240 | func = func->GetNext() ) | |
241 | { | |
242 | if ( m_toRun.Index(func->GetName()) == wxNOT_FOUND ) | |
243 | continue; | |
244 | ||
ebfa7cea VZ |
245 | wxString params; |
246 | if ( m_numParam ) | |
247 | params += wxString::Format(" with N=%ld", m_numParam); | |
248 | if ( !m_strParam.empty() ) | |
249 | { | |
250 | if ( !params.empty() ) | |
251 | params += " and"; | |
252 | params += wxString::Format(" with s=\"%s\"", m_strParam); | |
253 | } | |
254 | ||
255 | wxPrintf("Benchmarking %s%s: ", func->GetName(), params); | |
dc2ae355 VZ |
256 | |
257 | long timeMin = LONG_MAX, | |
258 | timeMax = 0, | |
259 | timeTotal = 0; | |
fa8825a0 VZ |
260 | bool ok = func->Init(); |
261 | for ( long a = 0; ok && a < m_avgCount; a++ ) | |
dc2ae355 VZ |
262 | { |
263 | wxStopWatch sw; | |
264 | for ( long n = 0; n < m_numRuns && ok; n++ ) | |
265 | { | |
266 | ok = func->Run(); | |
267 | } | |
268 | ||
269 | sw.Pause(); | |
270 | ||
dc2ae355 VZ |
271 | const long t = sw.Time(); |
272 | if ( t < timeMin ) | |
273 | timeMin = t; | |
274 | if ( t > timeMax ) | |
275 | timeMax = t; | |
276 | timeTotal += t; | |
277 | } | |
278 | ||
fa8825a0 VZ |
279 | func->Done(); |
280 | ||
dc2ae355 VZ |
281 | if ( !ok ) |
282 | { | |
283 | wxPrintf("ERROR\n"); | |
284 | rc = EXIT_FAILURE; | |
285 | } | |
286 | else | |
287 | { | |
288 | wxPrintf("%ldms total, ", timeTotal); | |
289 | ||
290 | long times = m_avgCount; | |
291 | if ( m_avgCount > 2 ) | |
292 | { | |
293 | timeTotal -= timeMin + timeMax; | |
294 | times -= 2; | |
295 | } | |
296 | ||
297 | wxPrintf("%.2f avg (min=%ld, max=%ld)\n", | |
298 | (float)timeTotal / times, timeMin, timeMax); | |
299 | } | |
ad1ca296 VZ |
300 | |
301 | fflush(stdout); | |
dc2ae355 VZ |
302 | } |
303 | ||
304 | return rc; | |
305 | } | |
306 | ||
307 | int BenchApp::OnExit() | |
308 | { | |
309 | #if wxUSE_GUI | |
310 | delete GetTopWindow(); | |
311 | #endif // wxUSE_GUI | |
312 | ||
313 | return 0; | |
314 | } | |
315 | ||
316 | /* static */ | |
317 | void BenchApp::ListBenchmarks() | |
318 | { | |
319 | wxPrintf("Available benchmarks:\n"); | |
320 | for ( Bench::Function *func = Bench::Function::GetFirst(); | |
321 | func; | |
322 | func = func->GetNext() ) | |
323 | { | |
324 | wxPrintf("\t%s\n", func->GetName()); | |
325 | } | |
326 | } |