1 /////////////////////////////////////////////////////////////////////////////
2 // Name: printfbench.cpp
3 // Purpose: A sample console app which benchmarks wxPrintf*() functions
4 // Author: Francesco Montorsi
8 // Copyright: (c) 2006 Francesco Montorsi
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
27 #include <wx/string.h>
30 #include <wx/stopwatch.h>
32 #include <wx/cmdline.h>
34 #include <wx/wxchar.h>
37 // ----------------------------------------------------------------------------
39 // ----------------------------------------------------------------------------
41 #define HELP_SWITCH "h"
42 #define NUMBENCHMARK_OPTION "n"
44 static const wxCmdLineEntryDesc g_cmdLineDesc
[] =
46 { wxCMD_LINE_SWITCH
, HELP_SWITCH
, "help",
47 "displays help on the command line parameters" },
49 { wxCMD_LINE_OPTION
, NUMBENCHMARK_OPTION
, "numtest",
50 "the number of wxPrintf() calls to benchmark", wxCMD_LINE_VAL_NUMBER
},
56 // ----------------------------------------------------------------------------
58 // ----------------------------------------------------------------------------
60 #define DEFAULT_NUMBENCHMARKS 100000
63 // set wxTEST_WX_ONLY to 1 when you want to profile wx's implementation only.
64 // A little reminder about profiling under Linux:
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()
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"
76 #define wxTEST_WX_ONLY 1
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");
84 // ----------------------------------------------------------------------------
85 // benchmarking helpers
86 // ----------------------------------------------------------------------------
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());
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);
102 #define DO_BENCHMARK(fnc) \
103 fnc(buffer, BUFSIZE, \
104 wxT("This is a short %s string with very few words"), wxT("test"));
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"));
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
118 #define wxSYSTEM_HAS_POSPARAM_SUPPORT 1
121 // we need to avoid the use of wxPrintf() here since it could have been mapped
122 // to wxWidgets' implementation of wxVsnPrintf() !
124 #define sys_printf swprintf
126 #define sys_printf snprintf
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))
136 // ----------------------------------------------------------------------------
138 // ----------------------------------------------------------------------------
140 int main(int argc
, char **argv
)
142 wxApp::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE
, "program");
143 wxInitializer initializer
;
146 fprintf(stderr
, "Failed to initialize the wxWidgets library, aborting.");
151 // parse the command line
152 // ----------------------
154 wxCmdLineParser
cmdParser(g_cmdLineDesc
, argc
, argv
);
155 if (cmdParser
.Parse() != 0)
158 if (cmdParser
.Found(HELP_SWITCH
))
165 if (!cmdParser
.Found(NUMBENCHMARK_OPTION
, &tests
))
166 tests
= DEFAULT_NUMBENCHMARKS
;
170 // print some info useful to compare different benchmarks
171 // -------------------------------------------------------
173 wxPrintf(wxT("\nRunning on %s\n"), wxGetOsDescription().c_str());
174 wxPrintf(wxT("Compiled in %s-%s-%s mode...\n\n"),
191 wxPrintf(wxT("Running %ld tests, for each configuration/implementation\n\n"), tests
);
196 // ----------------------
198 wxChar buffer
[BUFSIZE
];
202 #if wxUSE_PRINTF_POS_PARAMS
204 for (int i
=0; i
< tests
; i
++)
206 DO_LONG_POSITIONAL_BENCHMARK(wxSnprintf
)
207 DO_POSITIONAL_BENCHMARK(wxSnprintf
)
212 // benchmark system implementation of snprintf()
214 for (int i
=0; i
< tests
; i
++)
216 DO_LONG_BENCHMARK(sys_printf
)
217 DO_BENCHMARK(sys_printf
)
221 #if wxSYSTEM_HAS_POSPARAM_SUPPORT
223 for (int i
=0; i
< tests
; i
++)
225 DO_LONG_POSITIONAL_BENCHMARK(wxSnprintf
)
226 DO_POSITIONAL_BENCHMARK(wxSnprintf
)
231 #else // !wxTEST_WX_ONLY
234 wxStopWatch wxPos
, sys
, sysPos
;
239 #endif // !wxTEST_WX_ONLY
241 // benchmark wxWidgets implementation of wxSnprintf()
243 for (int i
=0; i
< tests
; i
++)
245 DO_LONG_BENCHMARK(wxSnprintf
)
246 DO_BENCHMARK(wxSnprintf
)
251 // ----------------------
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
));
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
));
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;
267 medium
= (double)wx
.Time() / (double)sys
.Time();
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
);
278 wxPrintf(wxT("\n\n"));