From bacf934f35c51baf49d0b73cf4fb79e860e24303 Mon Sep 17 00:00:00 2001 From: Arvid Ephraim Picciani Date: Mon, 9 Aug 2010 15:28:59 -0700 Subject: add performance comparisons to qregexp benchmark Reviewed-by: hjk --- tests/benchmarks/corelib/tools/qregexp/main.cpp | 304 +++++++++++++++++++++ tests/benchmarks/corelib/tools/qregexp/qregexp.pro | 11 +- tests/benchmarks/corelib/tools/qregexp/qregexp.qrc | 6 + 3 files changed, 320 insertions(+), 1 deletion(-) create mode 100644 tests/benchmarks/corelib/tools/qregexp/qregexp.qrc diff --git a/tests/benchmarks/corelib/tools/qregexp/main.cpp b/tests/benchmarks/corelib/tools/qregexp/main.cpp index ab9ed71..51cde95 100644 --- a/tests/benchmarks/corelib/tools/qregexp/main.cpp +++ b/tests/benchmarks/corelib/tools/qregexp/main.cpp @@ -38,16 +38,27 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + #include #include #include +#include #include +#ifdef HAVE_BOOST +#include +#endif + +#include +#include "pcre/pcre.h" +#define ZLIB_VERSION "1.2.3.4" class tst_qregexp : public QObject { Q_OBJECT +public: + tst_qregexp(); private slots: void escape_old(); void escape_old_data() { escape_data(); } @@ -59,10 +70,56 @@ private slots: void escape_new3_data() { escape_data(); } void escape_new4(); void escape_new4_data() { escape_data(); } +/* + JSC outperforms everything. + Boost is less impressive then expected. + */ + void simpleFind1(); + void rangeReplace1(); + void matchReplace1(); + + void simpleFind2(); + void rangeReplace2(); + void matchReplace2(); + + void simpleFindJSC(); + void rangeReplaceJSC(); + void matchReplaceJSC(); + +#ifdef HAVE_BOOST + void simpleFindBoost(); + void rangeReplaceBoost(); + void matchReplaceBoost(); +#endif + +/* those apply an (incorrect) regexp on entire source + (this main.cpp). JSC appears to handle this + (ab)use case best. QRegExp performs extremly bad. + */ + void horribleWrongReplace1(); + void horribleReplace1(); + void horribleReplace2(); + void horribleWrongReplace2(); + void horribleWrongReplaceJSC(); + void horribleReplaceJSC(); +#ifdef HAVE_BOOST + void horribleWrongReplaceBoost(); + void horribleReplaceBoost(); +#endif private: + QString str1; + QString str2; void escape_data(); }; +tst_qregexp::tst_qregexp() + :QObject() + ,str1("We are all happy monkeys") +{ + QFile f(":/main.cpp"); + f.open(QFile::ReadOnly); + str2=f.readAll(); +} static void verify(const QString "ed, const QString &expected) { @@ -285,6 +342,253 @@ void tst_qregexp::escape_new4() // "return quoted" } } + + +void tst_qregexp::simpleFind1() +{ + int roff; + QRegExp rx("happy"); + rx.setPatternSyntax(QRegExp::RegExp); + QBENCHMARK{ + roff = rx.indexIn(str1); + } + QCOMPARE(roff, 11); +} + +void tst_qregexp::rangeReplace1() +{ + QString r; + QRegExp rx("[a-f]"); + rx.setPatternSyntax(QRegExp::RegExp); + QBENCHMARK{ + r = QString(str1).replace(rx, "-"); + } + QCOMPARE(r, QString("W- -r- -ll h-ppy monk-ys")); +} + +void tst_qregexp::matchReplace1() +{ + QString r; + QRegExp rx("[^a-f]*([a-f]+)[^a-f]*"); + rx.setPatternSyntax(QRegExp::RegExp); + QBENCHMARK{ + r = QString(str1).replace(rx, "\\1"); + } + QCOMPARE(r, QString("eaeaae")); +} + +void tst_qregexp::horribleWrongReplace1() +{ + QString r; + QRegExp rx(".*#""define ZLIB_VERSION \"([0-9]+)\\.([0-9]+)\\.([0-9]+)\".*"); + rx.setPatternSyntax(QRegExp::RegExp); + QBENCHMARK{ + r = QString(str2).replace(rx, "\\1.\\2.\\3"); + } + QCOMPARE(r, str2); +} + +void tst_qregexp::horribleReplace1() +{ + QString r; + QRegExp rx(".*#""define ZLIB_VERSION \"([0-9]+)\\.([0-9]+)\\.([0-9]+).*"); + rx.setPatternSyntax(QRegExp::RegExp); + QBENCHMARK{ + r = QString(str2).replace(rx, "\\1.\\2.\\3"); + } + QCOMPARE(r, QString("1.2.3")); +} + + +void tst_qregexp::simpleFind2() +{ + int roff; + QRegExp rx("happy"); + rx.setPatternSyntax(QRegExp::RegExp2); + QBENCHMARK{ + roff = rx.indexIn(str1); + } + QCOMPARE(roff, 11); +} + +void tst_qregexp::rangeReplace2() +{ + QString r; + QRegExp rx("[a-f]"); + rx.setPatternSyntax(QRegExp::RegExp2); + QBENCHMARK{ + r = QString(str1).replace(rx, "-"); + } + QCOMPARE(r, QString("W- -r- -ll h-ppy monk-ys")); +} + +void tst_qregexp::matchReplace2() +{ + QString r; + QRegExp rx("[^a-f]*([a-f]+)[^a-f]*"); + rx.setPatternSyntax(QRegExp::RegExp2); + QBENCHMARK{ + r = QString(str1).replace(rx, "\\1"); + } + QCOMPARE(r, QString("eaeaae")); +} + +void tst_qregexp::horribleWrongReplace2() +{ + QString r; + QRegExp rx(".*#""define ZLIB_VERSION \"([0-9]+)\\.([0-9]+)\\.([0-9]+)\".*"); + rx.setPatternSyntax(QRegExp::RegExp2); + QBENCHMARK{ + r = QString(str2).replace(rx, "\\1.\\2.\\3"); + } + QCOMPARE(r, str2); +} + +void tst_qregexp::horribleReplace2() +{ + QString r; + QRegExp rx(".*#""define ZLIB_VERSION \"([0-9]+)\\.([0-9]+)\\.([0-9]+).*"); + rx.setPatternSyntax(QRegExp::RegExp2); + QBENCHMARK{ + r = QString(str2).replace(rx, "\\1.\\2.\\3"); + } + QCOMPARE(r, QString("1.2.3")); +} + + +void tst_qregexp::simpleFindJSC() +{ + int numr; + const char * errmsg=" "; + QString rxs("happy"); + JSRegExp *rx = jsRegExpCompile(rxs.utf16(), rxs.length(), JSRegExpDoNotIgnoreCase, JSRegExpSingleLine, 0, &errmsg); + QVERIFY(rx != 0); + QString s(str1); + int offsetVector[3]; + QBENCHMARK{ + numr = jsRegExpExecute(rx, s.utf16(), s.length(), 0, offsetVector, 3); + } + jsRegExpFree(rx); + QCOMPARE(numr, 1); + QCOMPARE(offsetVector[0], 11); +} + +void tst_qregexp::rangeReplaceJSC() +{ + QScriptValue r; + QScriptEngine engine; + engine.globalObject().setProperty("s", str1); + QScriptValue replaceFunc = engine.evaluate("(function() { return s.replace(/[a-f]/g, '-') } )"); + QVERIFY(replaceFunc.isFunction()); + QBENCHMARK{ + r = replaceFunc.call(QScriptValue()); + } + QCOMPARE(r.toString(), QString("W- -r- -ll h-ppy monk-ys")); +} + +void tst_qregexp::matchReplaceJSC() +{ + QScriptValue r; + QScriptEngine engine; + engine.globalObject().setProperty("s", str1); + QScriptValue replaceFunc = engine.evaluate("(function() { return s.replace(/[^a-f]*([a-f]+)[^a-f]*/g, '$1') } )"); + QVERIFY(replaceFunc.isFunction()); + QBENCHMARK{ + r = replaceFunc.call(QScriptValue()); + } + QCOMPARE(r.toString(), QString("eaeaae")); +} + +void tst_qregexp::horribleWrongReplaceJSC() +{ + QScriptValue r; + QScriptEngine engine; + engine.globalObject().setProperty("s", str2); + QScriptValue replaceFunc = engine.evaluate("(function() { return s.replace(/.*#""define ZLIB_VERSION \"([0-9]+)\\.([0-9]+)\\.([0-9]+)\".*/gm, '$1.$2.$3') } )"); + QVERIFY(replaceFunc.isFunction()); + QBENCHMARK{ + r = replaceFunc.call(QScriptValue()); + } + QCOMPARE(r.toString(), str2); +} + +void tst_qregexp::horribleReplaceJSC() +{ + QScriptValue r; + QScriptEngine engine; + // the m flag doesnt actually work here; dunno + engine.globalObject().setProperty("s", str2.replace('\n', ' ')); + QScriptValue replaceFunc = engine.evaluate("(function() { return s.replace(/.*#""define ZLIB_VERSION \"([0-9]+)\\.([0-9]+)\\.([0-9]+).*/gm, '$1.$2.$3') } )"); + QVERIFY(replaceFunc.isFunction()); + QBENCHMARK{ + r = replaceFunc.call(QScriptValue()); + } + QCOMPARE(r.toString(), QString("1.2.3")); +} + + +#ifdef HAVE_BOOST +void tst_qregexp::simpleFindBoost(){ + int roff; + boost::regex rx ("happy", boost::regex_constants::perl); + std::string s = str1.toStdString(); + std::string::const_iterator start, end; + start = s.begin(); + end = s.end(); + boost::match_flag_type flags = boost::match_default; + QBENCHMARK{ + boost::match_results what; + regex_search(start, end, what, rx, flags); + roff = (what[0].first)-start; + } + QCOMPARE(roff, 11); +} + +void tst_qregexp::rangeReplaceBoost() +{ + boost::regex pattern ("[a-f]", boost::regex_constants::perl); + std::string s = str1.toStdString(); + std::string r; + QBENCHMARK{ + r = boost::regex_replace (s, pattern, "-"); + } + QCOMPARE(r, std::string("W- -r- -ll h-ppy monk-ys")); +} + +void tst_qregexp::matchReplaceBoost() +{ + boost::regex pattern ("[^a-f]*([a-f]+)[^a-f]*",boost::regex_constants::perl); + std::string s = str1.toStdString(); + std::string r; + QBENCHMARK{ + r = boost::regex_replace (s, pattern, "$1"); + } + QCOMPARE(r, std::string("eaeaae")); +} + +void tst_qregexp::horribleWrongReplaceBoost() +{ + boost::regex pattern (".*#""define ZLIB_VERSION \"([0-9]+)\\.([0-9]+)\\.([0-9]+)\".*", boost::regex_constants::perl); + std::string s = str2.toStdString(); + std::string r; + QBENCHMARK{ + r = boost::regex_replace (s, pattern, "$1.$2.$3"); + } + QCOMPARE(r, s); +} + +void tst_qregexp::horribleReplaceBoost() +{ + boost::regex pattern (".*#""define ZLIB_VERSION \"([0-9]+)\\.([0-9]+)\\.([0-9]+).*", boost::regex_constants::perl); + std::string s = str2.toStdString(); + std::string r; + QBENCHMARK{ + r = boost::regex_replace (s, pattern, "$1.$2.$3"); + } + QCOMPARE(r, std::string("1.2.3")); +} +#endif //HAVE_BOOST + QTEST_MAIN(tst_qregexp) #include "main.moc" diff --git a/tests/benchmarks/corelib/tools/qregexp/qregexp.pro b/tests/benchmarks/corelib/tools/qregexp/qregexp.pro index e0f47c9..ffdad12 100644 --- a/tests/benchmarks/corelib/tools/qregexp/qregexp.pro +++ b/tests/benchmarks/corelib/tools/qregexp/qregexp.pro @@ -3,10 +3,19 @@ TEMPLATE = app TARGET = tst_bench_qregexp DEPENDPATH += . INCLUDEPATH += . - +RESOURCES+=qregexp.qrc QT -= gui +QT += script CONFIG += release # Input SOURCES += main.cpp + +include( $${QT_SOURCE_TREE}/src/3rdparty/webkit/JavaScriptCore/JavaScriptCore.pri ) + +exists( /usr/include/boost/regex.hpp ){ +DEFINES+=HAVE_BOOST +LIBS+=-lboost_regex +} + diff --git a/tests/benchmarks/corelib/tools/qregexp/qregexp.qrc b/tests/benchmarks/corelib/tools/qregexp/qregexp.qrc new file mode 100644 index 0000000..a7fe13c --- /dev/null +++ b/tests/benchmarks/corelib/tools/qregexp/qregexp.qrc @@ -0,0 +1,6 @@ + + + main.cpp + + + -- cgit v0.12