diff options
author | Christian Kandeler <christian.kandeler@qt.io> | 2017-11-13 12:11:50 +0100 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@qt.io> | 2017-11-13 17:10:30 +0000 |
commit | f4653dee55764138a941bf4c4551b2af9a5256da (patch) | |
tree | d795480cf390c10a4883dede65ee06772e5ea7bc /tests/benchmarker | |
parent | 0e09782513f9cfa09184e9d9c5cf5b1aa4ca2c94 (diff) |
Benchmarker: Keep raw data in case a regression is detected
If the difference between the old and new instruction count and/or
memory usage is higher than a (user-configurable) threshold, do not
remove the temporary directory and direct the user to its location. This
way, they can investigate the regression right away, rather than having
to re-run valgrind etc.
Change-Id: I8a35fde073806fa9daf0b28315a827207f8bd04d
Reviewed-by: Jake Petroules <jake.petroules@qt.io>
Diffstat (limited to 'tests/benchmarker')
-rw-r--r-- | tests/benchmarker/benchmarker-main.cpp | 51 | ||||
-rw-r--r-- | tests/benchmarker/benchmarker.cpp | 8 | ||||
-rw-r--r-- | tests/benchmarker/benchmarker.h | 2 | ||||
-rw-r--r-- | tests/benchmarker/commandlineparser.cpp | 13 | ||||
-rw-r--r-- | tests/benchmarker/commandlineparser.h | 2 |
5 files changed, 55 insertions, 21 deletions
diff --git a/tests/benchmarker/benchmarker-main.cpp b/tests/benchmarker/benchmarker-main.cpp index cb84576e2..e9d483f96 100644 --- a/tests/benchmarker/benchmarker-main.cpp +++ b/tests/benchmarker/benchmarker-main.cpp @@ -37,19 +37,24 @@ using namespace qbsBenchmarker; -static QByteArray relativeChange(qint64 oldVal, qint64 newVal) +static bool hasRegression = false; + +static int relativeChange(qint64 oldVal, qint64 newVal) +{ + return newVal == 0 ? 0 : newVal * 100 / oldVal - 100; +} + +static QByteArray relativeChangeString(int change) { - QByteArray change = newVal == 0 - ? "0" : QByteArray::number(std::abs(newVal * 100 / oldVal - 100)); - change += " %"; - if (oldVal > newVal) - change.prepend('-'); - else if (oldVal < newVal) - change.prepend('+'); - return change; + QByteArray changeString = QByteArray::number(change); + changeString += " %"; + if (change > 0) + changeString.prepend('+'); + return changeString; } -static void printResults(Activity activity, const BenchmarkResults &results) +static void printResults(Activity activity, const BenchmarkResults &results, + int regressionThreshold) { std::cout << "========== Performance data for "; switch (activity) { @@ -68,26 +73,33 @@ static void printResults(Activity activity, const BenchmarkResults &results) const char * const indent = " "; std::cout << indent << "Old instruction count: " << result.oldInstructionCount << std::endl; std::cout << indent << "New instruction count: " << result.newInstructionCount << std::endl; + int change = relativeChange(result.oldInstructionCount, result.newInstructionCount); + if (change > regressionThreshold) + hasRegression = true; std::cout << indent << "Relative change: " - << relativeChange(result.oldInstructionCount, result.newInstructionCount).constData() + << relativeChangeString(change).constData() << std::endl; std::cout << indent << "Old peak memory usage: " << result.oldPeakMemoryUsage << " Bytes" << std::endl; std::cout << indent << "New peak memory usage: " << result.newPeakMemoryUsage << " Bytes" << std::endl; + change = relativeChange(result.oldPeakMemoryUsage, result.newPeakMemoryUsage); + if (change > regressionThreshold) + hasRegression = true; std::cout << indent << "Relative change: " - << relativeChange(result.oldPeakMemoryUsage, result.newPeakMemoryUsage).constData() + << relativeChangeString(change).constData() << std::endl; } -static void printResults(Activities activities, const BenchmarkResults &results) +static void printResults(Activities activities, const BenchmarkResults &results, + int regressionThreshold) { if (activities & ActivityResolving) - printResults(ActivityResolving, results); + printResults(ActivityResolving, results, regressionThreshold); if (activities & ActivityRuleExecution) - printResults(ActivityRuleExecution, results); + printResults(ActivityRuleExecution, results, regressionThreshold); if (activities & ActivityNullBuild) - printResults(ActivityNullBuild, results); + printResults(ActivityNullBuild, results, regressionThreshold); } int main(int argc, char *argv[]) @@ -99,7 +111,12 @@ int main(int argc, char *argv[]) Benchmarker benchmarker(clParser.activies(), clParser.oldCommit(), clParser.newCommit(), clParser.testProjectFilePath(), clParser.qbsRepoDirPath()); benchmarker.benchmark(); - printResults(clParser.activies(), benchmarker.results()); + printResults(clParser.activies(), benchmarker.results(), clParser.regressionThreshold()); + if (hasRegression) { + benchmarker.keepRawData(); + std::cout << "Performance regression detected. Raw benchmarking data available " + "under " << qPrintable(benchmarker.rawDataBaseDir()) << '.' << std::endl; + } } catch (const Exception &e) { std::cerr << qPrintable(e.description()) << std::endl; return EXIT_FAILURE; diff --git a/tests/benchmarker/benchmarker.cpp b/tests/benchmarker/benchmarker.cpp index 26d863aaa..e4fb7b509 100644 --- a/tests/benchmarker/benchmarker.cpp +++ b/tests/benchmarker/benchmarker.cpp @@ -63,19 +63,19 @@ void Benchmarker::benchmark() { rememberCurrentRepoState(); runProcess(QStringList() << "git" << "checkout" << m_oldCommit, m_qbsRepo); - const QString oldQbsBuildDir = m_baseOutputDir.path() + "/old-qbs-build"; + const QString oldQbsBuildDir = m_baseOutputDir.path() + "/qbs-build." + m_oldCommit; std::cout << "Building from old repo state..." << std::endl; buildQbs(oldQbsBuildDir); runProcess(QStringList() << "git" << "checkout" << m_newCommit, m_qbsRepo); - const QString newQbsBuildDir = m_baseOutputDir.path() + "/new-qbs-build"; + const QString newQbsBuildDir = m_baseOutputDir.path() + "/qbs-build." + m_newCommit; std::cout << "Building from new repo state..." << std::endl; buildQbs(newQbsBuildDir); std::cout << "Now running valgrind. This can take a while." << std::endl; ValgrindRunner oldDataRetriever(m_activities, m_testProject, oldQbsBuildDir, - m_baseOutputDir.path() + "/old-stuff"); + m_baseOutputDir.path() + "/benchmark-data." + m_oldCommit); ValgrindRunner newDataRetriever(m_activities, m_testProject, newQbsBuildDir, - m_baseOutputDir.path() + "/new-stuff"); + m_baseOutputDir.path() + "/benchmark-data." + m_newCommit); QFuture<void> oldFuture = QtConcurrent::run(&oldDataRetriever, &ValgrindRunner::run); QFuture<void> newFuture = QtConcurrent::run(&newDataRetriever, &ValgrindRunner::run); oldFuture.waitForFinished(); diff --git a/tests/benchmarker/benchmarker.h b/tests/benchmarker/benchmarker.h index b6995de41..7027c9d15 100644 --- a/tests/benchmarker/benchmarker.h +++ b/tests/benchmarker/benchmarker.h @@ -58,8 +58,10 @@ public: ~Benchmarker(); void benchmark(); + void keepRawData() { m_baseOutputDir.setAutoRemove(false ); } BenchmarkResults results() const { return m_results; } + QString rawDataBaseDir() const { return m_baseOutputDir.path(); } private: void rememberCurrentRepoState(); diff --git a/tests/benchmarker/commandlineparser.cpp b/tests/benchmarker/commandlineparser.cpp index 84650cfdc..f33fdcaf4 100644 --- a/tests/benchmarker/commandlineparser.cpp +++ b/tests/benchmarker/commandlineparser.cpp @@ -65,6 +65,11 @@ void CommandLineParser::parse() .arg(resolveActivity(), ruleExecutionActivity(), nullBuildActivity(), allActivities()), "activities", allActivities()); parser.addOption(activitiesOption); + QCommandLineOption thresholdOption("regression-threshold", + "A relative increase higher than this is considered a performance regression. " + "All temporary data from running the benchmarks will be kept if that happens.", + "value in per cent"); + parser.addOption(thresholdOption); parser.process(*QCoreApplication::instance()); QList<QCommandLineOption> mandatoryOptions = QList<QCommandLineOption>() << oldCommitOption << newCommitOption << testProjectOption << qbsRepoOption; @@ -94,6 +99,14 @@ void CommandLineParser::parse() throwException(activitiesOption.names().first(), activityString, parser.helpText()); } } + m_regressionThreshold = 5; + if (parser.isSet(thresholdOption)) { + bool ok = true; + const QString rawThresholdValue = parser.value(thresholdOption); + m_regressionThreshold = rawThresholdValue.toInt(&ok); + if (!ok) + throwException(thresholdOption.names().first(), rawThresholdValue, parser.helpText()); + } } void CommandLineParser::throwException(const QString &optionName, const QString &illegalValue, diff --git a/tests/benchmarker/commandlineparser.h b/tests/benchmarker/commandlineparser.h index bdb3b0eda..2c87daeef 100644 --- a/tests/benchmarker/commandlineparser.h +++ b/tests/benchmarker/commandlineparser.h @@ -46,6 +46,7 @@ public: QString newCommit() const { return m_newCommit; } QString testProjectFilePath() const { return m_testProjectFilePath; } QString qbsRepoDirPath() const { return m_qbsRepoDirPath; } + int regressionThreshold() const { return m_regressionThreshold; } private: [[noreturn]] void throwException(const QString &optionName, const QString &illegalValue, @@ -57,6 +58,7 @@ private: QString m_newCommit; QString m_testProjectFilePath; QString m_qbsRepoDirPath; + int m_regressionThreshold; }; } // namespace qbsBenchmarker |