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