3f66f6a5b3
This keyword is not expanded by Git which means it's not replaced with the correct revision value in the releases made using git-based scripts and it's confusing to have lines with unexpanded "$Id$" in the released files. As expanding them with Git is not that simple (it could be done with git archive and export-subst attribute) and there are not many benefits in having them in the first place, just remove all these lines. If nothing else, this will make an eventual transition to Git simpler. Closes #14487. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74602 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
456 lines
11 KiB
C++
456 lines
11 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: tests/benchmarks/strings.cpp
|
|
// Purpose: String-related benchmarks
|
|
// Author: Vadim Zeitlin
|
|
// Created: 2008-07-19
|
|
// Copyright: (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "wx/string.h"
|
|
#include "wx/ffile.h"
|
|
|
|
#include "bench.h"
|
|
#include "htmlparser/htmlpars.h"
|
|
|
|
static const char asciistr[] =
|
|
"This is just the first line of a very long 7 bit ASCII string"
|
|
"This is just the second line of a very long 7 bit ASCII string"
|
|
"This is just the third line of a very long 7 bit ASCII string"
|
|
"This is just the fourth line of a very long 7 bit ASCII string"
|
|
"This is just the fifth line of a very long 7 bit ASCII string"
|
|
"This is just the sixth line of a very long 7 bit ASCII string"
|
|
"This is just the seventh line of a very long 7 bit ASCII string"
|
|
"This is just the eighth line of a very long 7 bit ASCII string"
|
|
"This is just the ninth line of a very long 7 bit ASCII string"
|
|
"This is just the tenth line of a very long 7 bit ASCII string"
|
|
;
|
|
|
|
static const char utf8str[] =
|
|
"\xD0\xA6\xD0\xB5\xD0\xBB\xD0\xBE\xD0\xB5 \xD1\x87\xD0\xB8\xD1\x81\xD0\xBB\xD0\xBE 0"
|
|
"\xD0\xA6\xD0\xB5\xD0\xBB\xD0\xBE\xD0\xB5 \xD1\x87\xD0\xB8\xD1\x81\xD0\xBB\xD0\xBE 1"
|
|
"\xD0\xA6\xD0\xB5\xD0\xBB\xD0\xBE\xD0\xB5 \xD1\x87\xD0\xB8\xD1\x81\xD0\xBB\xD0\xBE 2"
|
|
"\xD0\xA6\xD0\xB5\xD0\xBB\xD0\xBE\xD0\xB5 \xD1\x87\xD0\xB8\xD1\x81\xD0\xBB\xD0\xBE 3"
|
|
"\xD0\xA6\xD0\xB5\xD0\xBB\xD0\xBE\xD0\xB5 \xD1\x87\xD0\xB8\xD1\x81\xD0\xBB\xD0\xBE 4"
|
|
"\xD0\xA6\xD0\xB5\xD0\xBB\xD0\xBE\xD0\xB5 \xD1\x87\xD0\xB8\xD1\x81\xD0\xBB\xD0\xBE 5"
|
|
"\xD0\xA6\xD0\xB5\xD0\xBB\xD0\xBE\xD0\xB5 \xD1\x87\xD0\xB8\xD1\x81\xD0\xBB\xD0\xBE 6"
|
|
"\xD0\xA6\xD0\xB5\xD0\xBB\xD0\xBE\xD0\xB5 \xD1\x87\xD0\xB8\xD1\x81\xD0\xBB\xD0\xBE 7"
|
|
"\xD0\xA6\xD0\xB5\xD0\xBB\xD0\xBE\xD0\xB5 \xD1\x87\xD0\xB8\xD1\x81\xD0\xBB\xD0\xBE 8"
|
|
"\xD0\xA6\xD0\xB5\xD0\xBB\xD0\xBE\xD0\xB5 \xD1\x87\xD0\xB8\xD1\x81\xD0\xBB\xD0\xBE 9"
|
|
;
|
|
|
|
namespace
|
|
{
|
|
|
|
const wxString& GetTestAsciiString()
|
|
{
|
|
static wxString testString;
|
|
if ( testString.empty() )
|
|
{
|
|
long num = Bench::GetNumericParameter();
|
|
if ( !num )
|
|
num = 1;
|
|
|
|
for ( long n = 0; n < num; n++ )
|
|
testString += wxString::FromAscii(asciistr);
|
|
}
|
|
|
|
return testString;
|
|
}
|
|
|
|
} // anonymous namespace
|
|
|
|
// this is just a baseline
|
|
BENCHMARK_FUNC(Strlen)
|
|
{
|
|
if ( strlen(utf8str) != WXSIZEOF(utf8str) - 1 )
|
|
return false;
|
|
|
|
if ( strlen(asciistr) != WXSIZEOF(asciistr) - 1 )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// FromUTF8() benchmarks
|
|
// ----------------------------------------------------------------------------
|
|
|
|
BENCHMARK_FUNC(FromUTF8)
|
|
{
|
|
wxString s = wxString::FromUTF8(utf8str);
|
|
if ( s.empty() )
|
|
return false;
|
|
|
|
s = wxString::FromUTF8(asciistr);
|
|
if ( s.empty() )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
BENCHMARK_FUNC(FromUTF8WithNpos)
|
|
{
|
|
wxString s = wxString::FromUTF8(utf8str, wxString::npos);
|
|
if ( s.empty() )
|
|
return false;
|
|
|
|
s = wxString::FromUTF8(asciistr, wxString::npos);
|
|
if ( s.empty() )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
BENCHMARK_FUNC(FromUTF8WithLen)
|
|
{
|
|
wxString s = wxString::FromUTF8(utf8str, WXSIZEOF(utf8str));
|
|
if ( s.empty() )
|
|
return false;
|
|
|
|
s = wxString::FromUTF8(asciistr, WXSIZEOF(asciistr));
|
|
if ( s.empty() )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// FromUTF8Unchecked() benchmarks
|
|
// ----------------------------------------------------------------------------
|
|
|
|
BENCHMARK_FUNC(FromUTF8Unchecked)
|
|
{
|
|
wxString s = wxString::FromUTF8Unchecked(utf8str);
|
|
if ( s.empty() )
|
|
return false;
|
|
|
|
s = wxString::FromUTF8Unchecked(asciistr);
|
|
if ( s.empty() )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
BENCHMARK_FUNC(FromUTF8UncheckedWithNpos)
|
|
{
|
|
wxString s = wxString::FromUTF8Unchecked(utf8str, wxString::npos);
|
|
if ( s.empty() )
|
|
return false;
|
|
|
|
s = wxString::FromUTF8Unchecked(asciistr, wxString::npos);
|
|
if ( s.empty() )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
BENCHMARK_FUNC(FromUTF8UncheckedWithLen)
|
|
{
|
|
wxString s = wxString::FromUTF8Unchecked(utf8str, WXSIZEOF(utf8str));
|
|
if ( s.empty() )
|
|
return false;
|
|
|
|
s = wxString::FromUTF8Unchecked(asciistr, WXSIZEOF(asciistr));
|
|
if ( s.empty() )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// FromAscii() benchmarks
|
|
// ----------------------------------------------------------------------------
|
|
|
|
BENCHMARK_FUNC(FromAscii)
|
|
{
|
|
wxString s = wxString::FromAscii(asciistr);
|
|
if ( s.empty() )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
BENCHMARK_FUNC(FromAsciiWithNpos)
|
|
{
|
|
wxString s = wxString::FromAscii(asciistr);
|
|
if ( s.empty() )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
BENCHMARK_FUNC(FromAsciiWithLen)
|
|
{
|
|
wxString s = wxString::FromAscii(asciistr, WXSIZEOF(asciistr));
|
|
if ( s.empty() )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// simple string iteration
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// baseline
|
|
BENCHMARK_FUNC(ForCString)
|
|
{
|
|
for ( size_t n = 0; n < WXSIZEOF(asciistr); n++ )
|
|
{
|
|
if ( asciistr[n] == '~' )
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
BENCHMARK_FUNC(ForStringIndex)
|
|
{
|
|
const wxString& s = GetTestAsciiString();
|
|
const size_t len = s.length();
|
|
for ( size_t n = 0; n < len; n++ )
|
|
{
|
|
if ( s[n] == '~' )
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
BENCHMARK_FUNC(ForStringIter)
|
|
{
|
|
const wxString& s = GetTestAsciiString();
|
|
const wxString::const_iterator end = s.end();
|
|
for ( wxString::const_iterator i = s.begin(); i != end; ++i )
|
|
{
|
|
if ( *i == '~' )
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
BENCHMARK_FUNC(ForStringRIter)
|
|
{
|
|
const wxString& s = GetTestAsciiString();
|
|
const wxString::const_reverse_iterator rend = s.rend();
|
|
for ( wxString::const_reverse_iterator i = s.rbegin(); i != rend; ++i )
|
|
{
|
|
if ( *i == '~' )
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxString::Replace()
|
|
// ----------------------------------------------------------------------------
|
|
|
|
const size_t ASCIISTR_LEN = strlen(asciistr);
|
|
|
|
BENCHMARK_FUNC(ReplaceLoop)
|
|
{
|
|
wxString str('x', ASCIISTR_LEN);
|
|
for ( size_t n = 0; n < ASCIISTR_LEN; n++ )
|
|
{
|
|
if ( str[n] == 'a' )
|
|
str[n] = 'z';
|
|
}
|
|
|
|
return str.length() != 0;
|
|
}
|
|
|
|
BENCHMARK_FUNC(ReplaceNone)
|
|
{
|
|
wxString str('x', ASCIISTR_LEN);
|
|
return str.Replace("a", "z") == 0;
|
|
}
|
|
|
|
BENCHMARK_FUNC(ReplaceSome)
|
|
{
|
|
wxString str(asciistr);
|
|
return str.Replace("7", "8") != 0;
|
|
}
|
|
|
|
BENCHMARK_FUNC(ReplaceAll)
|
|
{
|
|
wxString str('x', ASCIISTR_LEN);
|
|
return str.Replace("x", "y") != 0;
|
|
}
|
|
|
|
BENCHMARK_FUNC(ReplaceLonger)
|
|
{
|
|
wxString str('x', ASCIISTR_LEN);
|
|
return str.Replace("x", "yy") != 0;
|
|
}
|
|
|
|
BENCHMARK_FUNC(ReplaceShorter)
|
|
{
|
|
wxString str('x', ASCIISTR_LEN);
|
|
return str.Replace("xx", "y") != 0;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// string case conversion
|
|
// ----------------------------------------------------------------------------
|
|
|
|
BENCHMARK_FUNC(Lower)
|
|
{
|
|
return GetTestAsciiString().Lower().length() > 0;
|
|
}
|
|
|
|
BENCHMARK_FUNC(Upper)
|
|
{
|
|
return GetTestAsciiString().Upper().length() > 0;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// string comparison
|
|
// ----------------------------------------------------------------------------
|
|
|
|
BENCHMARK_FUNC(StrcmpA)
|
|
{
|
|
const wxString& s = GetTestAsciiString();
|
|
|
|
return wxCRT_StrcmpA(s.c_str(), s.c_str()) == 0;
|
|
}
|
|
|
|
BENCHMARK_FUNC(StrcmpW)
|
|
{
|
|
const wxString& s = GetTestAsciiString();
|
|
|
|
return wxCRT_StrcmpW(s.wc_str(), s.wc_str()) == 0;
|
|
}
|
|
|
|
BENCHMARK_FUNC(StricmpA)
|
|
{
|
|
const wxString& s = GetTestAsciiString();
|
|
|
|
return wxCRT_StricmpA(s.c_str(), s.c_str()) == 0;
|
|
}
|
|
|
|
BENCHMARK_FUNC(StricmpW)
|
|
{
|
|
const wxString& s = GetTestAsciiString();
|
|
|
|
return wxCRT_StricmpW(s.wc_str(), s.wc_str()) == 0;
|
|
}
|
|
|
|
BENCHMARK_FUNC(StringCmp)
|
|
{
|
|
const wxString& s = GetTestAsciiString();
|
|
|
|
return s.Cmp(s) == 0;
|
|
}
|
|
|
|
BENCHMARK_FUNC(StringCmpNoCase)
|
|
{
|
|
const wxString& s = GetTestAsciiString();
|
|
|
|
return s.CmpNoCase(s) == 0;
|
|
}
|
|
|
|
// Also benchmark various native functions under MSW. Surprisingly/annoyingly
|
|
// they sometimes have vastly better performance than alternatives, especially
|
|
// for case-sensitive comparison (see #10375).
|
|
#ifdef __WINDOWS__
|
|
|
|
#include "wx/msw/wrapwin.h"
|
|
|
|
BENCHMARK_FUNC(MSWlstrcmp)
|
|
{
|
|
const wxString& s = GetTestAsciiString();
|
|
|
|
return lstrcmp(s.t_str(), s.t_str()) == 0;
|
|
}
|
|
|
|
BENCHMARK_FUNC(MSWlstrcmpi)
|
|
{
|
|
const wxString& s = GetTestAsciiString();
|
|
|
|
return lstrcmpi(s.t_str(), s.t_str()) == 0;
|
|
}
|
|
|
|
BENCHMARK_FUNC(MSWCompareString)
|
|
{
|
|
const wxString& s = GetTestAsciiString();
|
|
|
|
return ::CompareString
|
|
(
|
|
LOCALE_USER_DEFAULT,
|
|
0,
|
|
s.t_str(), s.length(),
|
|
s.t_str(), s.length()
|
|
) == CSTR_EQUAL;
|
|
}
|
|
|
|
BENCHMARK_FUNC(MSWCompareStringIgnoreCase)
|
|
{
|
|
const wxString& s = GetTestAsciiString();
|
|
|
|
return ::CompareString
|
|
(
|
|
LOCALE_USER_DEFAULT,
|
|
NORM_IGNORECASE,
|
|
s.t_str(), s.length(),
|
|
s.t_str(), s.length()
|
|
) == CSTR_EQUAL;
|
|
}
|
|
|
|
#endif // __WINDOWS__
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// string buffers: wx[W]CharBuffer
|
|
// ----------------------------------------------------------------------------
|
|
|
|
BENCHMARK_FUNC(CharBuffer)
|
|
{
|
|
wxString str(asciistr);
|
|
|
|
// NB: wxStrlen() is here to simulate some use of the returned buffer.
|
|
// Both mb_str() and wc_str() are used so that this code does something
|
|
// nontrivial in any build.
|
|
return wxStrlen(str.mb_str()) == ASCIISTR_LEN &&
|
|
wxStrlen(str.wc_str()) == ASCIISTR_LEN;
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxString::operator[] - parse large HTML page
|
|
// ----------------------------------------------------------------------------
|
|
|
|
class DummyParser : public wx28HtmlParser
|
|
{
|
|
public:
|
|
virtual wxObject* GetProduct() { return NULL; }
|
|
virtual void AddText(const wxChar*) {}
|
|
};
|
|
|
|
|
|
BENCHMARK_FUNC(ParseHTML)
|
|
{
|
|
// static so that construction time is not counted
|
|
static DummyParser parser;
|
|
static wxString html;
|
|
if ( html.empty() )
|
|
{
|
|
wxString html1;
|
|
wxFFile("htmltest.html").ReadAll(&html1, wxConvUTF8);
|
|
|
|
// this is going to make for some invalid HTML, of course, but it
|
|
// doesn't really matter
|
|
long num = Bench::GetNumericParameter();
|
|
if ( !num )
|
|
num = 1;
|
|
|
|
for ( long n = 0; n < num; n++ )
|
|
html += html1;
|
|
}
|
|
|
|
parser.Parse(html);
|
|
|
|
return true;
|
|
}
|