]> git.saurik.com Git - wxWidgets.git/blob - tests/benchmarks/printfbench.cpp
in STL build wxVector elements need to be assignable as well as copy constructible
[wxWidgets.git] / tests / benchmarks / printfbench.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: printfbench.cpp
3 // Purpose: A sample console app which benchmarks wxPrintf*() functions
4 // Author: Francesco Montorsi
5 // Modified by:
6 // Created: 27/3/2006
7 // RCS-ID: $Id$
8 // Copyright: (c) 2006 Francesco Montorsi
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 //
13 // Profiling under Linux:
14 // =====================
15 //
16 // 1) configure wxWidgets in release mode
17 // 2) make sure that HAVE_UNIX98_PRINTF is undefined (just #defining it to zero
18 // does not work; you must comment out the entire #define) in your setup.h;
19 // and also that wxUSE_PRINTF_POS_PARAMS is set to 1; this will force the
20 // use of wx's own implementation of wxVsnprintf()
21 // 3) compile wx
22 // 4) set wxTEST_WX_ONLY to 1 and compile tests as well
23 //
24 // Now you have two main choices:
25 //
26 // - using gprof:
27 // 5) add to the Makefile of this test program the -pg option both to
28 // CXXFLAGS and to LDFLAGS
29 // 6) run the test
30 // 7) look at the gmon.out file with gprof utility
31 //
32 // - using valgrind:
33 // 4) run "valgrind --tool=callgrind ./printfbench"
34 // 5) run "kcachegrind dump_file_generated_by_callgrind"
35 //
36
37
38 // ============================================================================
39 // declarations
40 // ============================================================================
41
42 // ----------------------------------------------------------------------------
43 // headers
44 // ----------------------------------------------------------------------------
45
46 #include "testprec.h"
47
48 #ifdef __BORLANDC__
49 #pragma hdrstop
50 #endif
51
52 #ifndef WX_PRECOMP
53 #include <wx/string.h>
54 #endif // WX_PRECOMP
55
56 #include <wx/stopwatch.h>
57 #include <wx/utils.h>
58 #include <wx/cmdline.h>
59 #include <wx/app.h>
60 #include <wx/wxchar.h>
61
62
63 // ----------------------------------------------------------------------------
64 // command line
65 // ----------------------------------------------------------------------------
66
67 #define HELP_SWITCH "h"
68 #define NUMBENCHMARK_OPTION "n"
69
70 static const wxCmdLineEntryDesc g_cmdLineDesc[] =
71 {
72 { wxCMD_LINE_SWITCH, HELP_SWITCH, "help",
73 "displays help on the command line parameters" },
74
75 { wxCMD_LINE_OPTION, NUMBENCHMARK_OPTION, "numtest",
76 "the number of wxPrintf() calls to benchmark", wxCMD_LINE_VAL_NUMBER },
77
78 { wxCMD_LINE_NONE }
79 };
80
81
82 // ----------------------------------------------------------------------------
83 // constants
84 // ----------------------------------------------------------------------------
85
86 #define DEFAULT_NUMBENCHMARKS 100000
87 #define BUFSIZE 10000
88
89 // set wxTEST_WX_ONLY to 1 when you want to profile wx's implementation only.
90 #define wxTEST_WX_ONLY 1
91
92
93 const wxString g_verylongString =
94 wxT("very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very ")
95 wxT("very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long string!\n\n\n");
96
97
98 // ----------------------------------------------------------------------------
99 // benchmarking helpers
100 // ----------------------------------------------------------------------------
101
102 #define DO_LONG_BENCHMARK(fnc) \
103 fnc(buffer, BUFSIZE, \
104 wxT("This is a reasonably long string with various %s arguments, exactly %d, ") \
105 wxT("and is used as benchmark for %s - %% %.2f %d %s"), \
106 wxT("(many!!)"), 6, wxT("this program"), 23.342f, 999, \
107 g_verylongString.c_str());
108
109 #define DO_LONG_POSITIONAL_BENCHMARK(fnc) \
110 fnc(buffer, BUFSIZE, \
111 wxT("This is a %2$s and thus is harder to parse... let's %1$s ") \
112 wxT("for our benchmarking aims - %% %3$f %5$d %4$s"), \
113 wxT("test it"), wxT("string with positional arguments"), 23.342f, \
114 g_verylongString.c_str(), 999);
115
116 #define DO_BENCHMARK(fnc) \
117 fnc(buffer, BUFSIZE, \
118 wxT("This is a short %s string with very few words"), wxT("test"));
119
120 #define DO_POSITIONAL_BENCHMARK(fnc) \
121 fnc(buffer, BUFSIZE, \
122 wxT("This is a %2$s and thus is harder to parse... nonetheless, %1$s !"), \
123 wxT("test it"), wxT("string with positional arguments"));
124
125 // the configure script of wxWidgets will define HAVE_UNIX98_PRINTF on those
126 // system with a *printf() family of functions conformant to Unix 98 standard;
127 // systems without the configure script as build system (e.g. Windows) do not
128 // have positional support anyway
129 #ifdef HAVE_UNIX98_PRINTF
130 #define wxSYSTEM_HAS_POSPARAM_SUPPORT 1
131 #else
132 #define wxSYSTEM_HAS_POSPARAM_SUPPORT 1
133 #endif
134
135 // we need to avoid the use of wxPrintf() here since it could have been mapped
136 // to wxWidgets' implementation of wxVsnPrintf() !
137 #if wxUSE_UNICODE
138 #define sys_printf swprintf
139 #else
140 #define sys_printf snprintf
141 #endif
142
143 // the given stopwatch returns a time delta in milliseconds thus this macro
144 // returns the number of microseconds required for a single *printf() call
145 #define wxFMT(sw) ((double)((sw.Time()*1000.0)/tests))
146
147
148
149
150 // ----------------------------------------------------------------------------
151 // main
152 // ----------------------------------------------------------------------------
153
154 int main(int argc, char **argv)
155 {
156 wxApp::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE, "program");
157 wxInitializer initializer;
158 if ( !initializer )
159 {
160 fprintf(stderr, "Failed to initialize the wxWidgets library, aborting.");
161
162 return -1;
163 }
164
165 // parse the command line
166 // ----------------------
167
168 wxCmdLineParser cmdParser(g_cmdLineDesc, argc, argv);
169 if (cmdParser.Parse() != 0)
170 return false;
171
172 if (cmdParser.Found(HELP_SWITCH))
173 {
174 cmdParser.Usage();
175 return false;
176 }
177
178 long tests;
179 if (!cmdParser.Found(NUMBENCHMARK_OPTION, &tests))
180 tests = DEFAULT_NUMBENCHMARKS;
181
182
183
184 // print some info useful to compare different benchmarks
185 // -------------------------------------------------------
186
187 wxPrintf(wxT("\nRunning on %s\n"), wxGetOsDescription().c_str());
188 wxPrintf(wxT("Compiled in %s-%s-%s mode...\n\n"),
189 #if wxUSE_UNICODE
190 wxT("unicode"),
191 #else
192 wxT("ansi"),
193 #endif
194 #ifdef __WXDEBUG__
195 wxT("debug"),
196 #else
197 wxT("release"),
198 #endif
199 #ifdef WXUSINGDLL
200 wxT("shared")
201 #else
202 wxT("static")
203 #endif
204 );
205 wxPrintf(wxT("Running %ld tests, for each configuration/implementation\n\n"), tests);
206
207
208
209 // start!
210 // ----------------------
211
212 wxChar buffer[BUFSIZE];
213
214 #if !wxTEST_WX_ONLY
215
216 #if wxUSE_PRINTF_POS_PARAMS
217 wxStopWatch wxPos;
218 for (int i=0; i < tests; i++)
219 {
220 DO_LONG_POSITIONAL_BENCHMARK(wxSnprintf)
221 DO_POSITIONAL_BENCHMARK(wxSnprintf)
222 }
223 wxPos.Pause();
224 #endif
225
226 // benchmark system implementation of snprintf()
227 wxStopWatch sys;
228 for (int i=0; i < tests; i++)
229 {
230 DO_LONG_BENCHMARK(sys_printf)
231 DO_BENCHMARK(sys_printf)
232 }
233 sys.Pause();
234
235 #if wxSYSTEM_HAS_POSPARAM_SUPPORT
236 wxStopWatch sysPos;
237 for (int i=0; i < tests; i++)
238 {
239 DO_LONG_POSITIONAL_BENCHMARK(wxSnprintf)
240 DO_POSITIONAL_BENCHMARK(wxSnprintf)
241 }
242 sysPos.Pause();
243 #endif
244
245 #else // !wxTEST_WX_ONLY
246
247 // fake stopwatches
248 wxStopWatch wxPos, sys, sysPos;
249 wxPos.Pause();
250 sys.Pause();
251 sysPos.Pause();
252
253 #endif // !wxTEST_WX_ONLY
254
255 // benchmark wxWidgets implementation of wxSnprintf()
256 wxStopWatch wx;
257 for (int i=0; i < tests; i++)
258 {
259 DO_LONG_BENCHMARK(wxSnprintf)
260 DO_BENCHMARK(wxSnprintf)
261 }
262 wx.Pause();
263
264 // print results
265 // ----------------------
266
267 wxPrintf(wxT("\n ============================== RESULTS ==============================\n"));
268 wxPrintf(wxT(" => Time for the system's snprintf(): %.5f microsec\n"), wxFMT(sys));
269 #if wxSYSTEM_HAS_POSPARAM_SUPPORT
270 wxPrintf(wxT(" => Time for the system's snprintf() with positionals: %.5f microsec\n"), wxFMT(sysPos));
271 #endif
272 wxPrintf(wxT(" => Time for wxSnprintf(): %.5f microsec\n"), wxFMT(wx));
273 #if wxUSE_PRINTF_POS_PARAMS
274 wxPrintf(wxT(" => Time for wxSnprintf() with positionals: %.5f microsec\n"), wxFMT(wxPos));
275 #endif
276
277 double medium;
278 #if wxSYSTEM_HAS_POSPARAM_SUPPORT && wxUSE_PRINTF_POS_PARAMS
279 medium = ((double)wx.Time() / (double)sys.Time() + (double)wxPos.Time() / (double)sysPos.Time()) / 2;
280 #else
281 medium = (double)wx.Time() / (double)sys.Time();
282 #endif
283
284 if (medium > 0.0)
285 {
286 // sometimes it happens that with a small number of tests, medium results zero;
287 // in that case doing the 1.0/medium will not be a wise thing!
288 wxPrintf(wxT("\nwxWidgets implementation is %.3f times slower\n")
289 wxT("(i.e. %.3f times faster) than system implementation.\n"), medium, 1.0/medium);
290 }
291
292 wxPrintf(wxT("\n\n"));
293 return 0;
294 }
295