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