strings.cpp 11 KB

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