From 80dc4ea49a14c90c21d6b45c08d8681c06d4db37 Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Thu, 1 Sep 2016 21:06:18 +0100 Subject: [PATCH] refs #710 Sample to compare performance of string utilities versus regular expressions. --- samples/blackmisc/main.cpp | 2 + samples/blackmisc/samplesperformance.cpp | 83 ++++++++++++++++++++++++ samples/blackmisc/samplesperformance.h | 3 + 3 files changed, 88 insertions(+) diff --git a/samples/blackmisc/main.cpp b/samples/blackmisc/main.cpp index dc85c2382..664393763 100644 --- a/samples/blackmisc/main.cpp +++ b/samples/blackmisc/main.cpp @@ -49,6 +49,7 @@ int main(int argc, char *argv[]) qtout << "6c .. 25/20 Performance impl. type" << endl; qtout << "6d .. 40/20 Interpolator scenario" << endl; qtout << "6e .. JSON performance" << endl; + qtout << "6f .. string utils vs. regex" << endl; qtout << "7 .. Algorithms" << endl; qtout << "-----" << endl; qtout << "x .. Bye" << endl; @@ -63,6 +64,7 @@ int main(int argc, char *argv[]) else if (s.startsWith("6c")) { CSamplesPerformance::samplesImplementationType(qtout, 25, 20); } else if (s.startsWith("6d")) { CSamplesPerformance::interpolatorScenario(qtout, 40, 20); } else if (s.startsWith("6e")) { CSamplesPerformance::samplesJson(qtout); } + else if (s.startsWith("6f")) { CSamplesPerformance::samplesString(qtout); } else if (s.startsWith("7")) { CSamplesAlgorithm::samples(); } else if (s.startsWith("x")) { break; } } diff --git a/samples/blackmisc/samplesperformance.cpp b/samples/blackmisc/samplesperformance.cpp index c5a65c51d..47436a92d 100644 --- a/samples/blackmisc/samplesperformance.cpp +++ b/samples/blackmisc/samplesperformance.cpp @@ -19,6 +19,7 @@ #include "blackmisc/aviation/callsign.h" #include "blackmisc/geo/coordinategeodetic.h" #include "blackmisc/pq/units.h" +#include "blackmisc/stringutils.h" #include "blackmisc/testing.h" #include @@ -36,6 +37,7 @@ #include #include +using namespace BlackMisc; using namespace BlackMisc::Aviation; using namespace BlackMisc::Geo; using namespace BlackMisc::PhysicalQuantities; @@ -340,6 +342,87 @@ namespace BlackSample return 0; } + int CSamplesPerformance::samplesString(QTextStream &out) + { + QTime timer; + static const QString chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~_-=+!\"@#$%^&*()[]{} \t;:\\/?,.<>"; + QStringList strings; + std::generate_n(std::back_inserter(strings), 100000, [] + { + QString s; + std::generate_n(std::back_inserter(s), 10, [] { return chars[qrand() % chars.size()]; }); + return s; + }); + QString bigString = strings.join("\n"); + + QRegularExpression upperRegex("[A-Z]"); + upperRegex.optimize(); + + timer.start(); + for (const QString &s : strings) + { + auto c = containsChar(s, [](QChar c) { return c.isUpper(); }); + Q_UNUSED(c); + } + out << "Check 100,000 strings for containing uppercase letter: (utility) " << timer.elapsed() << "ms" << endl; + + timer.start(); + for (const QString &s : strings) + { + auto c = s.contains(upperRegex); + Q_UNUSED(c); + } + out << "Check 100,000 strings for containing uppercase letter: (regex) " << timer.elapsed() << "ms" << endl << endl; + + timer.start(); + for (const QString &s : strings) + { + auto i = indexOfChar(s, [](QChar c) { return c.isUpper(); }); + Q_UNUSED(i); + } + out << "Check 100,000 strings for index of first uppercase letter: (utility) " << timer.elapsed() << "ms" << endl; + + timer.start(); + for (const QString &s : strings) + { + auto i = s.indexOf(upperRegex); + Q_UNUSED(i); + } + out << "Check 100,000 strings for index of first uppercase letter: (regex) " << timer.elapsed() << "ms" << endl << endl; + + auto temp = strings; + timer.start(); + for (QString &s : strings) + { + removeChars(s, [](QChar c) { return c.isUpper(); }); + } + out << "Remove from 100,000 strings all uppercase letters: (utility) " << timer.elapsed() << "ms" << endl; + strings = temp; + + timer.start(); + for (QString &s : strings) + { + s.remove(upperRegex); + } + out << "Remove from 100,000 strings all uppercase letters: (regex) " << timer.elapsed() << "ms" << endl << endl; + + timer.start(); + { + auto lines = splitLines(bigString); + Q_UNUSED(lines); + } + out << "Split 100,000 line string into list of lines: (QStringList) " << timer.elapsed() << "ms" << endl; + + timer.start(); + { + auto lines = splitLinesRefs(bigString); + Q_UNUSED(lines); + } + out << "Split 100,000 line string into list of lines: (QList) " << timer.elapsed() << "ms" << endl; + + return 0; + } + CAircraftSituationList CSamplesPerformance::createSituations(qint64 baseTimeEpoch, int numberOfCallsigns, int numberOfTimes) { CAircraftSituationList situations; diff --git a/samples/blackmisc/samplesperformance.h b/samples/blackmisc/samplesperformance.h index f1d5e5a2c..d8960e2de 100644 --- a/samples/blackmisc/samplesperformance.h +++ b/samples/blackmisc/samplesperformance.h @@ -38,6 +38,9 @@ namespace BlackSample //! JSON (de)serialization static int samplesJson(QTextStream &out); + //! String manipulation + static int samplesString(QTextStream &out); + //! Situation values for testing static BlackMisc::Aviation::CAircraftSituationList createSituations(qint64 baseTimeEpoch, int numberOfCallsigns, int numberOfTimes);