]> git.saurik.com Git - wxWidgets.git/blame - tests/benchmarks/strings.cpp
Make wxMBConv_iconv MT-safe by not using wxString in it.
[wxWidgets.git] / tests / benchmarks / strings.cpp
CommitLineData
dc2ae355
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: tests/benchmarks/strings.cpp
3// Purpose: String-related benchmarks
4// Author: Vadim Zeitlin
5// Created: 2008-07-19
6// RCS-ID: $Id$
7// Copyright: (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
526954c5 8// Licence: wxWindows licence
dc2ae355
VZ
9/////////////////////////////////////////////////////////////////////////////
10
11#include "wx/string.h"
c21faa0a 12#include "wx/ffile.h"
dc2ae355
VZ
13
14#include "bench.h"
c21faa0a 15#include "htmlparser/htmlpars.h"
dc2ae355
VZ
16
17static const char asciistr[] =
18 "This is just the first line of a very long 7 bit ASCII string"
19 "This is just the second line of a very long 7 bit ASCII string"
20 "This is just the third line of a very long 7 bit ASCII string"
21 "This is just the fourth line of a very long 7 bit ASCII string"
22 "This is just the fifth line of a very long 7 bit ASCII string"
23 "This is just the sixth line of a very long 7 bit ASCII string"
24 "This is just the seventh line of a very long 7 bit ASCII string"
25 "This is just the eighth line of a very long 7 bit ASCII string"
26 "This is just the ninth line of a very long 7 bit ASCII string"
27 "This is just the tenth line of a very long 7 bit ASCII string"
28 ;
29
30static const char utf8str[] =
31 "\xD0\xA6\xD0\xB5\xD0\xBB\xD0\xBE\xD0\xB5 \xD1\x87\xD0\xB8\xD1\x81\xD0\xBB\xD0\xBE 0"
32 "\xD0\xA6\xD0\xB5\xD0\xBB\xD0\xBE\xD0\xB5 \xD1\x87\xD0\xB8\xD1\x81\xD0\xBB\xD0\xBE 1"
33 "\xD0\xA6\xD0\xB5\xD0\xBB\xD0\xBE\xD0\xB5 \xD1\x87\xD0\xB8\xD1\x81\xD0\xBB\xD0\xBE 2"
34 "\xD0\xA6\xD0\xB5\xD0\xBB\xD0\xBE\xD0\xB5 \xD1\x87\xD0\xB8\xD1\x81\xD0\xBB\xD0\xBE 3"
35 "\xD0\xA6\xD0\xB5\xD0\xBB\xD0\xBE\xD0\xB5 \xD1\x87\xD0\xB8\xD1\x81\xD0\xBB\xD0\xBE 4"
36 "\xD0\xA6\xD0\xB5\xD0\xBB\xD0\xBE\xD0\xB5 \xD1\x87\xD0\xB8\xD1\x81\xD0\xBB\xD0\xBE 5"
37 "\xD0\xA6\xD0\xB5\xD0\xBB\xD0\xBE\xD0\xB5 \xD1\x87\xD0\xB8\xD1\x81\xD0\xBB\xD0\xBE 6"
38 "\xD0\xA6\xD0\xB5\xD0\xBB\xD0\xBE\xD0\xB5 \xD1\x87\xD0\xB8\xD1\x81\xD0\xBB\xD0\xBE 7"
39 "\xD0\xA6\xD0\xB5\xD0\xBB\xD0\xBE\xD0\xB5 \xD1\x87\xD0\xB8\xD1\x81\xD0\xBB\xD0\xBE 8"
40 "\xD0\xA6\xD0\xB5\xD0\xBB\xD0\xBE\xD0\xB5 \xD1\x87\xD0\xB8\xD1\x81\xD0\xBB\xD0\xBE 9"
41 ;
42
33ccf3d1
VZ
43namespace
44{
45
46const wxString& GetTestAsciiString()
47{
48 static wxString testString;
49 if ( testString.empty() )
50 {
ebfa7cea
VZ
51 long num = Bench::GetNumericParameter();
52 if ( !num )
53 num = 1;
54
55 for ( long n = 0; n < num; n++ )
33ccf3d1
VZ
56 testString += wxString::FromAscii(asciistr);
57 }
58
59 return testString;
60}
61
62} // anonymous namespace
63
dc2ae355
VZ
64// this is just a baseline
65BENCHMARK_FUNC(Strlen)
66{
67 if ( strlen(utf8str) != WXSIZEOF(utf8str) - 1 )
68 return false;
69
70 if ( strlen(asciistr) != WXSIZEOF(asciistr) - 1 )
71 return false;
72
73 return true;
74}
75
76// ----------------------------------------------------------------------------
77// FromUTF8() benchmarks
78// ----------------------------------------------------------------------------
79
80BENCHMARK_FUNC(FromUTF8)
81{
82 wxString s = wxString::FromUTF8(utf8str);
83 if ( s.empty() )
84 return false;
85
86 s = wxString::FromUTF8(asciistr);
87 if ( s.empty() )
88 return false;
89
90 return true;
91}
92
93BENCHMARK_FUNC(FromUTF8WithNpos)
94{
95 wxString s = wxString::FromUTF8(utf8str, wxString::npos);
96 if ( s.empty() )
97 return false;
98
99 s = wxString::FromUTF8(asciistr, wxString::npos);
100 if ( s.empty() )
101 return false;
102
103 return true;
104}
105
106BENCHMARK_FUNC(FromUTF8WithLen)
107{
108 wxString s = wxString::FromUTF8(utf8str, WXSIZEOF(utf8str));
109 if ( s.empty() )
110 return false;
111
112 s = wxString::FromUTF8(asciistr, WXSIZEOF(asciistr));
113 if ( s.empty() )
114 return false;
115
116 return true;
117}
118
119// ----------------------------------------------------------------------------
120// FromUTF8Unchecked() benchmarks
121// ----------------------------------------------------------------------------
122
123BENCHMARK_FUNC(FromUTF8Unchecked)
124{
125 wxString s = wxString::FromUTF8Unchecked(utf8str);
126 if ( s.empty() )
127 return false;
128
129 s = wxString::FromUTF8Unchecked(asciistr);
130 if ( s.empty() )
131 return false;
132
133 return true;
134}
135
136BENCHMARK_FUNC(FromUTF8UncheckedWithNpos)
137{
138 wxString s = wxString::FromUTF8Unchecked(utf8str, wxString::npos);
139 if ( s.empty() )
140 return false;
141
142 s = wxString::FromUTF8Unchecked(asciistr, wxString::npos);
143 if ( s.empty() )
144 return false;
145
146 return true;
147}
148
149BENCHMARK_FUNC(FromUTF8UncheckedWithLen)
150{
151 wxString s = wxString::FromUTF8Unchecked(utf8str, WXSIZEOF(utf8str));
152 if ( s.empty() )
153 return false;
154
155 s = wxString::FromUTF8Unchecked(asciistr, WXSIZEOF(asciistr));
156 if ( s.empty() )
157 return false;
158
159 return true;
160}
161
162// ----------------------------------------------------------------------------
163// FromAscii() benchmarks
164// ----------------------------------------------------------------------------
165
166BENCHMARK_FUNC(FromAscii)
167{
168 wxString s = wxString::FromAscii(asciistr);
169 if ( s.empty() )
170 return false;
171
172 return true;
173}
174
175BENCHMARK_FUNC(FromAsciiWithNpos)
176{
177 wxString s = wxString::FromAscii(asciistr);
178 if ( s.empty() )
179 return false;
180
181 return true;
182}
183
184BENCHMARK_FUNC(FromAsciiWithLen)
185{
186 wxString s = wxString::FromAscii(asciistr, WXSIZEOF(asciistr));
187 if ( s.empty() )
188 return false;
189
190 return true;
191}
192
193// ----------------------------------------------------------------------------
194// simple string iteration
195// ----------------------------------------------------------------------------
196
197// baseline
198BENCHMARK_FUNC(ForCString)
199{
200 for ( size_t n = 0; n < WXSIZEOF(asciistr); n++ )
201 {
202 if ( asciistr[n] == '~' )
203 return false;
204 }
205
206 return true;
207}
208
209BENCHMARK_FUNC(ForStringIndex)
210{
33ccf3d1 211 const wxString& s = GetTestAsciiString();
dc2ae355
VZ
212 const size_t len = s.length();
213 for ( size_t n = 0; n < len; n++ )
214 {
215 if ( s[n] == '~' )
216 return false;
217 }
218
219 return true;
220}
221
222BENCHMARK_FUNC(ForStringIter)
223{
33ccf3d1 224 const wxString& s = GetTestAsciiString();
dc2ae355
VZ
225 const wxString::const_iterator end = s.end();
226 for ( wxString::const_iterator i = s.begin(); i != end; ++i )
227 {
228 if ( *i == '~' )
229 return false;
230 }
231
232 return true;
233}
234
235BENCHMARK_FUNC(ForStringRIter)
236{
33ccf3d1 237 const wxString& s = GetTestAsciiString();
dc2ae355
VZ
238 const wxString::const_reverse_iterator rend = s.rend();
239 for ( wxString::const_reverse_iterator i = s.rbegin(); i != rend; ++i )
240 {
241 if ( *i == '~' )
242 return false;
243 }
244
245 return true;
246}
247
9729777e
VZ
248// ----------------------------------------------------------------------------
249// wxString::Replace()
250// ----------------------------------------------------------------------------
251
0654c03a 252const size_t ASCIISTR_LEN = strlen(asciistr);
9729777e
VZ
253
254BENCHMARK_FUNC(ReplaceLoop)
255{
0654c03a
VS
256 wxString str('x', ASCIISTR_LEN);
257 for ( size_t n = 0; n < ASCIISTR_LEN; n++ )
9729777e
VZ
258 {
259 if ( str[n] == 'a' )
260 str[n] = 'z';
261 }
262
263 return str.length() != 0;
264}
265
543cf9ba 266BENCHMARK_FUNC(ReplaceNone)
9729777e 267{
0654c03a 268 wxString str('x', ASCIISTR_LEN);
543cf9ba
VZ
269 return str.Replace("a", "z") == 0;
270}
9729777e 271
543cf9ba
VZ
272BENCHMARK_FUNC(ReplaceSome)
273{
274 wxString str(asciistr);
275 return str.Replace("7", "8") != 0;
9729777e
VZ
276}
277
543cf9ba 278BENCHMARK_FUNC(ReplaceAll)
9729777e 279{
0654c03a 280 wxString str('x', ASCIISTR_LEN);
543cf9ba 281 return str.Replace("x", "y") != 0;
9729777e
VZ
282}
283
072682ce
VZ
284BENCHMARK_FUNC(ReplaceLonger)
285{
286 wxString str('x', ASCIISTR_LEN);
287 return str.Replace("x", "yy") != 0;
288}
289
290BENCHMARK_FUNC(ReplaceShorter)
291{
292 wxString str('x', ASCIISTR_LEN);
293 return str.Replace("xx", "y") != 0;
294}
295
05f68f2f
VZ
296// ----------------------------------------------------------------------------
297// string case conversion
298// ----------------------------------------------------------------------------
299
300BENCHMARK_FUNC(Lower)
301{
302 return GetTestAsciiString().Lower().length() > 0;
303}
304
305BENCHMARK_FUNC(Upper)
306{
307 return GetTestAsciiString().Upper().length() > 0;
308}
309
310// ----------------------------------------------------------------------------
311// string comparison
312// ----------------------------------------------------------------------------
313
314BENCHMARK_FUNC(StrcmpA)
315{
316 const wxString& s = GetTestAsciiString();
317
318 return wxCRT_StrcmpA(s, s) == 0;
319}
320
321BENCHMARK_FUNC(StrcmpW)
322{
323 const wxString& s = GetTestAsciiString();
324
325 return wxCRT_StrcmpW(s, s) == 0;
326}
327
328BENCHMARK_FUNC(StricmpA)
329{
330 const wxString& s = GetTestAsciiString();
331
332 return wxCRT_StricmpA(s, s) == 0;
333}
334
335BENCHMARK_FUNC(StricmpW)
336{
337 const wxString& s = GetTestAsciiString();
338
339 return wxCRT_StricmpW(s, s) == 0;
340}
341
342BENCHMARK_FUNC(StringCmp)
343{
344 const wxString& s = GetTestAsciiString();
345
346 return s.Cmp(s) == 0;
347}
348
349BENCHMARK_FUNC(StringCmpNoCase)
350{
351 const wxString& s = GetTestAsciiString();
352
353 return s.CmpNoCase(s) == 0;
354}
355
356// Also benchmark various native functions under MSW. Surprisingly/annoyingly
357// they sometimes have vastly better performance than alternatives, especially
358// for case-sensitive comparison (see #10375).
359#ifdef __WXMSW__
360
361#include "wx/msw/wrapwin.h"
362
363BENCHMARK_FUNC(MSWlstrcmp)
364{
365 const wxString& s = GetTestAsciiString();
366
367 return lstrcmp(s.t_str(), s.t_str()) == 0;
368}
369
370BENCHMARK_FUNC(MSWlstrcmpi)
371{
372 const wxString& s = GetTestAsciiString();
373
374 return lstrcmpi(s.t_str(), s.t_str()) == 0;
375}
376
377BENCHMARK_FUNC(MSWCompareString)
378{
379 const wxString& s = GetTestAsciiString();
380
381 return ::CompareString
382 (
383 LOCALE_USER_DEFAULT,
384 0,
385 s.t_str(), s.length(),
386 s.t_str(), s.length()
387 ) == CSTR_EQUAL;
388}
389
390BENCHMARK_FUNC(MSWCompareStringIgnoreCase)
391{
392 const wxString& s = GetTestAsciiString();
393
394 return ::CompareString
395 (
396 LOCALE_USER_DEFAULT,
397 NORM_IGNORECASE,
398 s.t_str(), s.length(),
399 s.t_str(), s.length()
400 ) == CSTR_EQUAL;
401}
402
403#endif // __WXMSW__
0654c03a
VS
404
405// ----------------------------------------------------------------------------
406// string buffers: wx[W]CharBuffer
407// ----------------------------------------------------------------------------
408
409BENCHMARK_FUNC(CharBuffer)
410{
411 wxString str(asciistr);
412
413 // NB: wxStrlen() is here to simulate some use of the returned buffer.
414 // Both mb_str() and wc_str() are used so that this code does something
415 // nontrivial in any build.
416 return wxStrlen(str.mb_str()) == ASCIISTR_LEN &&
417 wxStrlen(str.wc_str()) == ASCIISTR_LEN;
418}
c21faa0a
VS
419
420
421// ----------------------------------------------------------------------------
422// wxString::operator[] - parse large HTML page
423// ----------------------------------------------------------------------------
424
425class DummyParser : public wx28HtmlParser
426{
427public:
428 virtual wxObject* GetProduct() { return NULL; }
429 virtual void AddText(const wxChar*) {}
430};
431
432
433BENCHMARK_FUNC(ParseHTML)
434{
435 // static so that construction time is not counted
436 static DummyParser parser;
437 static wxString html;
438 if ( html.empty() )
439 {
8fad8b2e
VZ
440 wxString html1;
441 wxFFile("htmltest.html").ReadAll(&html1, wxConvUTF8);
442
443 // this is going to make for some invalid HTML, of course, but it
444 // doesn't really matter
ebfa7cea
VZ
445 long num = Bench::GetNumericParameter();
446 if ( !num )
447 num = 1;
448
449 for ( long n = 0; n < num; n++ )
8fad8b2e 450 html += html1;
c21faa0a
VS
451 }
452
453 parser.Parse(html);
454
455 return true;
456}