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 /////////////////////////////////////////////////////////////////////////////
13 // Profiling under Linux:
14 // =====================
16 // 1) configure wxWidgets in release mode
17 // 2) make sure that HAVE_UNIX98_PRINTF is undefined (just #defining it to zero
18 // does not work; you must comment out the entire #define) in your setup.h;
19 // and also that wxUSE_PRINTF_POS_PARAMS is set to 1; this will force the
20 // use of wx's own implementation of wxVsnprintf()
22 // 4) set wxTEST_WX_ONLY to 1 and compile tests as well
24 // Now you have two main choices:
27 // 5) add to the Makefile of this test program the -pg option both to
28 // CXXFLAGS and to LDFLAGS
30 // 7) look at the gmon.out file with gprof utility
33 // 4) run "valgrind --tool=callgrind ./printfbench"
34 // 5) run "kcachegrind dump_file_generated_by_callgrind"
38 // ============================================================================
40 // ============================================================================
42 // ----------------------------------------------------------------------------
44 // ----------------------------------------------------------------------------
53 #include <wx/string.h>
56 #include <wx/stopwatch.h>
58 #include <wx/cmdline.h>
60 #include <wx/wxchar.h>
63 // ----------------------------------------------------------------------------
65 // ----------------------------------------------------------------------------
67 #define HELP_SWITCH "h"
68 #define NUMBENCHMARK_OPTION "n"
70 static const wxCmdLineEntryDesc g_cmdLineDesc
[] =
72 { wxCMD_LINE_SWITCH
, HELP_SWITCH
, "help",
73 "displays help on the command line parameters" },
75 { wxCMD_LINE_OPTION
, NUMBENCHMARK_OPTION
, "numtest",
76 "the number of wxPrintf() calls to benchmark", wxCMD_LINE_VAL_NUMBER
},
82 // ----------------------------------------------------------------------------
84 // ----------------------------------------------------------------------------
86 #define DEFAULT_NUMBENCHMARKS 100000
89 // set wxTEST_WX_ONLY to 1 when you want to profile wx's implementation only.
90 #define wxTEST_WX_ONLY 1
93 const wxString g_verylongString
=
94 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 ")
95 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");
98 // ----------------------------------------------------------------------------
99 // benchmarking helpers
100 // ----------------------------------------------------------------------------
102 #define DO_LONG_BENCHMARK(fnc) \
103 fnc(buffer, BUFSIZE, \
104 wxT("This is a reasonably long string with various %s arguments, exactly %d, ") \
105 wxT("and is used as benchmark for %s - %% %.2f %d %s"), \
106 wxT("(many!!)"), 6, wxT("this program"), 23.342f, 999, \
107 g_verylongString.c_str());
109 #define DO_LONG_POSITIONAL_BENCHMARK(fnc) \
110 fnc(buffer, BUFSIZE, \
111 wxT("This is a %2$s and thus is harder to parse... let's %1$s ") \
112 wxT("for our benchmarking aims - %% %3$f %5$d %4$s"), \
113 wxT("test it"), wxT("string with positional arguments"), 23.342f, \
114 g_verylongString.c_str(), 999);
116 #define DO_BENCHMARK(fnc) \
117 fnc(buffer, BUFSIZE, \
118 wxT("This is a short %s string with very few words"), wxT("test"));
120 #define DO_POSITIONAL_BENCHMARK(fnc) \
121 fnc(buffer, BUFSIZE, \
122 wxT("This is a %2$s and thus is harder to parse... nonetheless, %1$s !"), \
123 wxT("test it"), wxT("string with positional arguments"));
125 // the configure script of wxWidgets will define HAVE_UNIX98_PRINTF on those
126 // system with a *printf() family of functions conformant to Unix 98 standard;
127 // systems without the configure script as build system (e.g. Windows) do not
128 // have positional support anyway
129 #ifdef HAVE_UNIX98_PRINTF
130 #define wxSYSTEM_HAS_POSPARAM_SUPPORT 1
132 #define wxSYSTEM_HAS_POSPARAM_SUPPORT 1
135 // we need to avoid the use of wxPrintf() here since it could have been mapped
136 // to wxWidgets' implementation of wxVsnPrintf() !
138 #define sys_printf swprintf
140 #define sys_printf snprintf
143 // the given stopwatch returns a time delta in milliseconds thus this macro
144 // returns the number of microseconds required for a single *printf() call
145 #define wxFMT(sw) ((double)((sw.Time()*1000.0)/tests))
150 // ----------------------------------------------------------------------------
152 // ----------------------------------------------------------------------------
154 int main(int argc
, char **argv
)
156 wxApp::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE
, "program");
157 wxInitializer initializer
;
160 fprintf(stderr
, "Failed to initialize the wxWidgets library, aborting.");
165 // parse the command line
166 // ----------------------
168 wxCmdLineParser
cmdParser(g_cmdLineDesc
, argc
, argv
);
169 if (cmdParser
.Parse() != 0)
172 if (cmdParser
.Found(HELP_SWITCH
))
179 if (!cmdParser
.Found(NUMBENCHMARK_OPTION
, &tests
))
180 tests
= DEFAULT_NUMBENCHMARKS
;
184 // print some info useful to compare different benchmarks
185 // -------------------------------------------------------
187 wxPrintf(wxT("\nRunning on %s\n"), wxGetOsDescription().c_str());
188 wxPrintf(wxT("Compiled in %s-%s-%s mode...\n\n"),
205 wxPrintf(wxT("Running %ld tests, for each configuration/implementation\n\n"), tests
);
210 // ----------------------
212 wxChar buffer
[BUFSIZE
];
216 #if wxUSE_PRINTF_POS_PARAMS
218 for (int i
=0; i
< tests
; i
++)
220 DO_LONG_POSITIONAL_BENCHMARK(wxSnprintf
)
221 DO_POSITIONAL_BENCHMARK(wxSnprintf
)
226 // benchmark system implementation of snprintf()
228 for (int i
=0; i
< tests
; i
++)
230 DO_LONG_BENCHMARK(sys_printf
)
231 DO_BENCHMARK(sys_printf
)
235 #if wxSYSTEM_HAS_POSPARAM_SUPPORT
237 for (int i
=0; i
< tests
; i
++)
239 DO_LONG_POSITIONAL_BENCHMARK(wxSnprintf
)
240 DO_POSITIONAL_BENCHMARK(wxSnprintf
)
245 #else // !wxTEST_WX_ONLY
248 wxStopWatch wxPos
, sys
, sysPos
;
253 #endif // !wxTEST_WX_ONLY
255 // benchmark wxWidgets implementation of wxSnprintf()
257 for (int i
=0; i
< tests
; i
++)
259 DO_LONG_BENCHMARK(wxSnprintf
)
260 DO_BENCHMARK(wxSnprintf
)
265 // ----------------------
267 wxPrintf(wxT("\n ============================== RESULTS ==============================\n"));
268 wxPrintf(wxT(" => Time for the system's snprintf(): %.5f microsec\n"), wxFMT(sys
));
269 #if wxSYSTEM_HAS_POSPARAM_SUPPORT
270 wxPrintf(wxT(" => Time for the system's snprintf() with positionals: %.5f microsec\n"), wxFMT(sysPos
));
272 wxPrintf(wxT(" => Time for wxSnprintf(): %.5f microsec\n"), wxFMT(wx
));
273 #if wxUSE_PRINTF_POS_PARAMS
274 wxPrintf(wxT(" => Time for wxSnprintf() with positionals: %.5f microsec\n"), wxFMT(wxPos
));
278 #if wxSYSTEM_HAS_POSPARAM_SUPPORT && wxUSE_PRINTF_POS_PARAMS
279 medium
= ((double)wx
.Time() / (double)sys
.Time() + (double)wxPos
.Time() / (double)sysPos
.Time()) / 2;
281 medium
= (double)wx
.Time() / (double)sys
.Time();
286 // sometimes it happens that with a small number of tests, medium results zero;
287 // in that case doing the 1.0/medium will not be a wise thing!
288 wxPrintf(wxT("\nwxWidgets implementation is %.3f times slower\n")
289 wxT("(i.e. %.3f times faster) than system implementation.\n"), medium
, 1.0/medium
);
292 wxPrintf(wxT("\n\n"));