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 // ----------------------------------------------------------------------------
20 #include <wx/string.h>
21 #include <wx/stopwatch.h>
23 #include <wx/cmdline.h>
27 // ----------------------------------------------------------------------------
29 // ----------------------------------------------------------------------------
31 #define HELP_SWITCH wxT("h")
32 #define NUMBENCHMARK_OPTION wxT("n")
34 static const wxCmdLineEntryDesc g_cmdLineDesc
[] =
36 { wxCMD_LINE_SWITCH
, HELP_SWITCH
, wxT("help"),
37 wxT("displays help on the command line parameters") },
39 { wxCMD_LINE_OPTION
, NUMBENCHMARK_OPTION
, wxT("numtest"),
40 wxT("the number of wxPrintf() calls to benchmark"), wxCMD_LINE_VAL_NUMBER
},
46 // ----------------------------------------------------------------------------
48 // ----------------------------------------------------------------------------
50 #define DEFAULT_NUMBENCHMARKS 100000
53 // set wxTEST_WX_ONLY to 1 when you want to profile wx's implementation only.
54 // A little reminder about profiling under Linux:
56 // 1) configure wxWidgets in release mode
57 // 2) make sure that HAVE_UNIX98_PRINTF is undefined (just #defining it to zero
58 // does not work; you must comment out the entire #define) in your setup.h;
59 // and also that wxUSE_PRINTF_POS_PARAMS is set to 1; this will force the
60 // use of wx's own implementation of wxVsnprintf()
62 // 4) set wxTEST_WX_ONLY to 1 and compile tests as well
63 // 5) run "callgrind ./printfbench"
64 // 6) run "kcachegrind dump_file_generated_by_callgrind"
66 #define wxTEST_WX_ONLY 1
69 const wxString g_verylongString
=
70 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 ")
71 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");
74 // ----------------------------------------------------------------------------
75 // benchmarking helpers
76 // ----------------------------------------------------------------------------
78 #define DO_LONG_BENCHMARK(fnc) \
79 fnc(buffer, BUFSIZE, \
80 wxT("This is a reasonably long string with various %s arguments, exactly %d, ") \
81 wxT("and is used as benchmark for %s - %% %.2f %d %s"), \
82 wxT("(many!!)"), 6, wxT("this program"), 23.342f, 999, \
83 g_verylongString.c_str());
85 #define DO_LONG_POSITIONAL_BENCHMARK(fnc) \
86 fnc(buffer, BUFSIZE, \
87 wxT("This is a %2$s and thus is harder to parse... let's %1$s ") \
88 wxT("for our benchmarking aims - %% %3$f %5$d %4$s"), \
89 wxT("test it"), wxT("string with positional arguments"), 23.342f, \
90 g_verylongString.c_str(), 999);
92 #define DO_BENCHMARK(fnc) \
93 fnc(buffer, BUFSIZE, \
94 wxT("This is a short %s string with very few words"), wxT("test"));
96 #define DO_POSITIONAL_BENCHMARK(fnc) \
97 fnc(buffer, BUFSIZE, \
98 wxT("This is a %2$s and thus is harder to parse... nonetheless, %1$s !"), \
99 wxT("test it"), wxT("string with positional arguments"));
101 // the configure script of wxWidgets will define HAVE_UNIX98_PRINTF on those
102 // system with a *printf() family of functions conformant to Unix 98 standard;
103 // systems without the configure script as build system (e.g. Windows) do not
104 // have positional support anyway
105 #ifdef HAVE_UNIX98_PRINTF
106 #define wxSYSTEM_HAS_POSPARAM_SUPPORT 1
108 #define wxSYSTEM_HAS_POSPARAM_SUPPORT 1
111 // we need to avoid the use of wxPrintf() here since it could have been mapped
112 // to wxWidgets' implementation of wxVsnPrintf() !
114 #define sys_printf swprintf
116 #define sys_printf snprintf
119 // the given stopwatch returns a time delta in milliseconds thus this macro
120 // returns the number of microseconds required for a single *printf() call
121 #define wxFMT(sw) ((double)((sw.Time()*1000.0)/tests))
126 // ----------------------------------------------------------------------------
128 // ----------------------------------------------------------------------------
130 int main(int argc
, char **argv
)
132 wxApp::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE
, "program");
133 wxInitializer initializer
;
136 fprintf(stderr
, "Failed to initialize the wxWidgets library, aborting.");
141 // parse the command line
142 // ----------------------
144 wxCmdLineParser
cmdParser(g_cmdLineDesc
, argc
, argv
);
145 if (cmdParser
.Parse() != 0)
148 if (cmdParser
.Found(HELP_SWITCH
))
155 if (!cmdParser
.Found(NUMBENCHMARK_OPTION
, &tests
))
156 tests
= DEFAULT_NUMBENCHMARKS
;
160 // print some info useful to compare different benchmarks
161 // -------------------------------------------------------
163 wxPrintf(wxT("\nRunning on %s\n"), wxGetOsDescription().c_str());
164 wxPrintf(wxT("Compiled in %s-%s-%s mode...\n\n"),
181 wxPrintf(wxT("Running %ld tests, for each configuration/implementation\n\n"), tests
);
186 // ----------------------
188 wxChar buffer
[BUFSIZE
];
192 #if wxUSE_PRINTF_POS_PARAMS
194 for (int i
=0; i
< tests
; i
++)
196 DO_LONG_POSITIONAL_BENCHMARK(wxSnprintf
)
197 DO_POSITIONAL_BENCHMARK(wxSnprintf
)
202 // benchmark system implementation of snprintf()
204 for (int i
=0; i
< tests
; i
++)
206 DO_LONG_BENCHMARK(sys_printf
)
207 DO_BENCHMARK(sys_printf
)
211 #if wxSYSTEM_HAS_POSPARAM_SUPPORT
213 for (int i
=0; i
< tests
; i
++)
215 DO_LONG_POSITIONAL_BENCHMARK(wxSnprintf
)
216 DO_POSITIONAL_BENCHMARK(wxSnprintf
)
221 #else // !wxTEST_WX_ONLY
224 wxStopWatch wxPos
, sys
, sysPos
;
229 #endif // !wxTEST_WX_ONLY
231 // benchmark wxWidgets implementation of wxSnprintf()
233 for (int i
=0; i
< tests
; i
++)
235 DO_LONG_BENCHMARK(wxSnprintf
)
236 DO_BENCHMARK(wxSnprintf
)
241 // ----------------------
243 wxPrintf(wxT("\n ============================== RESULTS ==============================\n"));
244 wxPrintf(wxT(" => Time for the system's snprintf(): %.5f microsec\n"), wxFMT(sys
));
245 #if wxSYSTEM_HAS_POSPARAM_SUPPORT
246 wxPrintf(wxT(" => Time for the system's snprintf() with positionals: %.5f microsec\n"), wxFMT(sysPos
));
248 wxPrintf(wxT(" => Time for wxSnprintf(): %.5f microsec\n"), wxFMT(wx
));
249 #if wxUSE_PRINTF_POS_PARAMS
250 wxPrintf(wxT(" => Time for wxSnprintf() with positionals: %.5f microsec\n"), wxFMT(wxPos
));
254 #if wxSYSTEM_HAS_POSPARAM_SUPPORT && wxUSE_PRINTF_POS_PARAMS
255 medium
= ((double)wx
.Time() / (double)sys
.Time() + (double)wxPos
.Time() / (double)sysPos
.Time()) / 2;
257 medium
= (double)wx
.Time() / (double)sys
.Time();
262 // sometimes it happens that with a small number of tests, medium results zero;
263 // in that case doing the 1.0/medium will not be a wise thing!
264 wxPrintf(wxT("\nwxWidgets implementation is %.3f times slower\n")
265 wxT("(i.e. %.3f times faster) than system implementation.\n"), medium
, 1.0/medium
);
268 wxPrintf(wxT("\n\n"));