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