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>
36 // ----------------------------------------------------------------------------
38 // ----------------------------------------------------------------------------
40 #define HELP_SWITCH wxT("h")
41 #define NUMBENCHMARK_OPTION wxT("n")
43 static const wxCmdLineEntryDesc g_cmdLineDesc
[] =
45 { wxCMD_LINE_SWITCH
, HELP_SWITCH
, wxT("help"),
46 wxT("displays help on the command line parameters") },
48 { wxCMD_LINE_OPTION
, NUMBENCHMARK_OPTION
, wxT("numtest"),
49 wxT("the number of wxPrintf() calls to benchmark"), wxCMD_LINE_VAL_NUMBER
},
55 // ----------------------------------------------------------------------------
57 // ----------------------------------------------------------------------------
59 #define DEFAULT_NUMBENCHMARKS 100000
62 // set wxTEST_WX_ONLY to 1 when you want to profile wx's implementation only.
63 // A little reminder about profiling under Linux:
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()
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"
75 #define wxTEST_WX_ONLY 1
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");
83 // ----------------------------------------------------------------------------
84 // benchmarking helpers
85 // ----------------------------------------------------------------------------
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());
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);
101 #define DO_BENCHMARK(fnc) \
102 fnc(buffer, BUFSIZE, \
103 wxT("This is a short %s string with very few words"), wxT("test"));
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"));
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
117 #define wxSYSTEM_HAS_POSPARAM_SUPPORT 1
120 // we need to avoid the use of wxPrintf() here since it could have been mapped
121 // to wxWidgets' implementation of wxVsnPrintf() !
123 #define sys_printf swprintf
125 #define sys_printf snprintf
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))
135 // ----------------------------------------------------------------------------
137 // ----------------------------------------------------------------------------
139 int main(int argc
, char **argv
)
141 wxApp::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE
, "program");
142 wxInitializer initializer
;
145 fprintf(stderr
, "Failed to initialize the wxWidgets library, aborting.");
150 // parse the command line
151 // ----------------------
153 wxCmdLineParser
cmdParser(g_cmdLineDesc
, argc
, argv
);
154 if (cmdParser
.Parse() != 0)
157 if (cmdParser
.Found(HELP_SWITCH
))
164 if (!cmdParser
.Found(NUMBENCHMARK_OPTION
, &tests
))
165 tests
= DEFAULT_NUMBENCHMARKS
;
169 // print some info useful to compare different benchmarks
170 // -------------------------------------------------------
172 wxPrintf(wxT("\nRunning on %s\n"), wxGetOsDescription().c_str());
173 wxPrintf(wxT("Compiled in %s-%s-%s mode...\n\n"),
190 wxPrintf(wxT("Running %ld tests, for each configuration/implementation\n\n"), tests
);
195 // ----------------------
197 wxChar buffer
[BUFSIZE
];
201 #if wxUSE_PRINTF_POS_PARAMS
203 for (int i
=0; i
< tests
; i
++)
205 DO_LONG_POSITIONAL_BENCHMARK(wxSnprintf
)
206 DO_POSITIONAL_BENCHMARK(wxSnprintf
)
211 // benchmark system implementation of snprintf()
213 for (int i
=0; i
< tests
; i
++)
215 DO_LONG_BENCHMARK(sys_printf
)
216 DO_BENCHMARK(sys_printf
)
220 #if wxSYSTEM_HAS_POSPARAM_SUPPORT
222 for (int i
=0; i
< tests
; i
++)
224 DO_LONG_POSITIONAL_BENCHMARK(wxSnprintf
)
225 DO_POSITIONAL_BENCHMARK(wxSnprintf
)
230 #else // !wxTEST_WX_ONLY
233 wxStopWatch wxPos
, sys
, sysPos
;
238 #endif // !wxTEST_WX_ONLY
240 // benchmark wxWidgets implementation of wxSnprintf()
242 for (int i
=0; i
< tests
; i
++)
244 DO_LONG_BENCHMARK(wxSnprintf
)
245 DO_BENCHMARK(wxSnprintf
)
250 // ----------------------
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
));
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
));
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;
266 medium
= (double)wx
.Time() / (double)sys
.Time();
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
);
277 wxPrintf(wxT("\n\n"));