]>
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 | |
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'; | |
8fad8b2e | 33 | static const char OPTION_NUMERIC_PARAM = 'p'; |
dc2ae355 VZ |
34 | |
35 | // ---------------------------------------------------------------------------- | |
36 | // BenchApp declaration | |
37 | // ---------------------------------------------------------------------------- | |
38 | ||
39 | #if wxUSE_GUI | |
40 | typedef wxApp BenchAppBase; | |
41 | #else | |
42 | typedef wxAppConsole BenchAppBase; | |
43 | #endif | |
44 | ||
45 | class BenchApp : public BenchAppBase | |
46 | { | |
47 | public: | |
48 | BenchApp(); | |
49 | ||
50 | // standard overrides | |
51 | virtual void OnInitCmdLine(wxCmdLineParser& parser); | |
52 | virtual bool OnCmdLineParsed(wxCmdLineParser& parser); | |
53 | virtual bool OnInit(); | |
54 | virtual int OnRun(); | |
55 | virtual int OnExit(); | |
56 | ||
8fad8b2e VZ |
57 | // accessor |
58 | int GetNumericParameter() const { return m_numParam; } | |
59 | ||
dc2ae355 VZ |
60 | private: |
61 | // list all registered benchmarks | |
62 | void ListBenchmarks(); | |
63 | ||
64 | // command lines options/parameters | |
65 | wxSortedArrayString m_toRun; | |
66 | long m_numRuns, | |
8fad8b2e VZ |
67 | m_avgCount, |
68 | m_numParam; | |
dc2ae355 VZ |
69 | }; |
70 | ||
8fad8b2e VZ |
71 | IMPLEMENT_APP_CONSOLE(BenchApp) |
72 | ||
dc2ae355 | 73 | // ============================================================================ |
8fad8b2e | 74 | // Bench namespace symbols implementation |
dc2ae355 VZ |
75 | // ============================================================================ |
76 | ||
77 | Bench::Function *Bench::Function::ms_head = NULL; | |
78 | ||
8fad8b2e VZ |
79 | long Bench::GetNumericParameter() |
80 | { | |
81 | return wxGetApp().GetNumericParameter(); | |
82 | } | |
83 | ||
dc2ae355 VZ |
84 | // ============================================================================ |
85 | // BenchApp implementation | |
86 | // ============================================================================ | |
87 | ||
dc2ae355 VZ |
88 | BenchApp::BenchApp() |
89 | { | |
90 | m_avgCount = 10; | |
91 | m_numRuns = 10000; // just some default (TODO: switch to time-based one) | |
8fad8b2e | 92 | m_numParam = 1; |
dc2ae355 VZ |
93 | } |
94 | ||
95 | bool BenchApp::OnInit() | |
96 | { | |
97 | if ( !BenchAppBase::OnInit() ) | |
98 | return false; | |
99 | ||
100 | wxPrintf("wxWidgets benchmarking program\n" | |
101 | "Build: %s\n", WX_BUILD_OPTIONS_SIGNATURE); | |
102 | ||
103 | #if wxUSE_GUI | |
104 | // create a hidden parent window to be used as parent for the GUI controls | |
105 | new wxFrame(NULL, wxID_ANY, "Hidden wx benchmark frame"); | |
106 | #endif // wxUSE_GUI | |
107 | ||
108 | return true; | |
109 | } | |
110 | ||
111 | void BenchApp::OnInitCmdLine(wxCmdLineParser& parser) | |
112 | { | |
113 | BenchAppBase::OnInitCmdLine(parser); | |
114 | ||
115 | parser.AddSwitch(OPTION_LIST, | |
116 | "list", | |
117 | "list all the existing benchmarks"); | |
118 | ||
119 | parser.AddOption(OPTION_AVG_COUNT, | |
120 | "avg-count", | |
c517ecec VZ |
121 | wxString::Format |
122 | ( | |
123 | "number of times to run benchmarking loop (default: %ld)", | |
124 | m_avgCount | |
125 | ), | |
dc2ae355 VZ |
126 | wxCMD_LINE_VAL_NUMBER); |
127 | parser.AddOption(OPTION_NUM_RUNS, | |
128 | "num-runs", | |
c517ecec VZ |
129 | wxString::Format |
130 | ( | |
131 | "number of times to run each benchmark in a loop " | |
132 | "(default: %ld)", | |
133 | m_numRuns | |
134 | ), | |
dc2ae355 | 135 | wxCMD_LINE_VAL_NUMBER); |
8fad8b2e VZ |
136 | parser.AddOption(OPTION_NUMERIC_PARAM, |
137 | "num-param", | |
138 | "numeric parameter used by some benchmark functions " | |
139 | "(default: 1)", | |
140 | wxCMD_LINE_VAL_NUMBER); | |
141 | ||
dc2ae355 VZ |
142 | parser.AddParam("benchmark name", |
143 | wxCMD_LINE_VAL_STRING, | |
144 | wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_PARAM_MULTIPLE); | |
145 | } | |
146 | ||
147 | bool BenchApp::OnCmdLineParsed(wxCmdLineParser& parser) | |
148 | { | |
149 | if ( parser.Found(OPTION_LIST) ) | |
150 | { | |
151 | ListBenchmarks(); | |
152 | ||
153 | return false; | |
154 | } | |
155 | ||
156 | const size_t count = parser.GetParamCount(); | |
157 | if ( !count ) | |
158 | { | |
159 | parser.Usage(); | |
160 | ||
161 | ListBenchmarks(); | |
162 | ||
163 | return false; | |
164 | } | |
165 | ||
166 | parser.Found(OPTION_AVG_COUNT, &m_avgCount); | |
167 | parser.Found(OPTION_NUM_RUNS, &m_numRuns); | |
8fad8b2e | 168 | parser.Found(OPTION_NUMERIC_PARAM, &m_numParam); |
dc2ae355 VZ |
169 | |
170 | // construct sorted array for quick verification of benchmark names | |
171 | wxSortedArrayString benchmarks; | |
172 | for ( Bench::Function *func = Bench::Function::GetFirst(); | |
173 | func; | |
174 | func = func->GetNext() ) | |
175 | { | |
176 | benchmarks.push_back(func->GetName()); | |
177 | } | |
178 | ||
179 | for ( size_t n = 0; n < count; n++ ) | |
180 | { | |
181 | const wxString name = parser.GetParam(n); | |
182 | if ( benchmarks.Index(name) == wxNOT_FOUND ) | |
183 | { | |
184 | wxFprintf(stderr, "No benchmark named \"%s\".\n", name); | |
185 | return false; | |
186 | } | |
187 | ||
188 | m_toRun.push_back(name); | |
189 | } | |
190 | ||
191 | return BenchAppBase::OnCmdLineParsed(parser); | |
192 | } | |
193 | ||
194 | int BenchApp::OnRun() | |
195 | { | |
196 | int rc = EXIT_SUCCESS; | |
197 | for ( Bench::Function *func = Bench::Function::GetFirst(); | |
198 | func; | |
199 | func = func->GetNext() ) | |
200 | { | |
201 | if ( m_toRun.Index(func->GetName()) == wxNOT_FOUND ) | |
202 | continue; | |
203 | ||
8fad8b2e | 204 | wxPrintf("Benchmarking %s(%ld): ", func->GetName(), m_numParam); |
dc2ae355 VZ |
205 | |
206 | long timeMin = LONG_MAX, | |
207 | timeMax = 0, | |
208 | timeTotal = 0; | |
209 | bool ok = true; | |
210 | for ( long a = 0; a < m_avgCount; a++ ) | |
211 | { | |
212 | wxStopWatch sw; | |
213 | for ( long n = 0; n < m_numRuns && ok; n++ ) | |
214 | { | |
215 | ok = func->Run(); | |
216 | } | |
217 | ||
218 | sw.Pause(); | |
219 | ||
220 | if ( !ok ) | |
221 | break; | |
222 | ||
223 | const long t = sw.Time(); | |
224 | if ( t < timeMin ) | |
225 | timeMin = t; | |
226 | if ( t > timeMax ) | |
227 | timeMax = t; | |
228 | timeTotal += t; | |
229 | } | |
230 | ||
231 | if ( !ok ) | |
232 | { | |
233 | wxPrintf("ERROR\n"); | |
234 | rc = EXIT_FAILURE; | |
235 | } | |
236 | else | |
237 | { | |
238 | wxPrintf("%ldms total, ", timeTotal); | |
239 | ||
240 | long times = m_avgCount; | |
241 | if ( m_avgCount > 2 ) | |
242 | { | |
243 | timeTotal -= timeMin + timeMax; | |
244 | times -= 2; | |
245 | } | |
246 | ||
247 | wxPrintf("%.2f avg (min=%ld, max=%ld)\n", | |
248 | (float)timeTotal / times, timeMin, timeMax); | |
249 | } | |
250 | } | |
251 | ||
252 | return rc; | |
253 | } | |
254 | ||
255 | int BenchApp::OnExit() | |
256 | { | |
257 | #if wxUSE_GUI | |
258 | delete GetTopWindow(); | |
259 | #endif // wxUSE_GUI | |
260 | ||
261 | return 0; | |
262 | } | |
263 | ||
264 | /* static */ | |
265 | void BenchApp::ListBenchmarks() | |
266 | { | |
267 | wxPrintf("Available benchmarks:\n"); | |
268 | for ( Bench::Function *func = Bench::Function::GetFirst(); | |
269 | func; | |
270 | func = func->GetNext() ) | |
271 | { | |
272 | wxPrintf("\t%s\n", func->GetName()); | |
273 | } | |
274 | } |