summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorjasplin <qt-info@nokia.com>2010-04-28 14:38:05 +0200
committerjasplin <qt-info@nokia.com>2010-04-28 14:38:05 +0200
commitbcbf85fab1d038d2ef9a204800a8d517cef73bc5 (patch)
tree6fcab5ed391554a274aa77e04d1c2e7f77c8afd8 /src
parentf3f295510bb2db4af5c10a04955666cadcaa5089 (diff)
Evaluate the index only at timestamps with results.
The index is now evaluated only at timestamps for which at least one contributing result exist. These are the exact timestamps at which the index may potentially change the value.
Diffstat (limited to 'src')
-rw-r--r--src/bm/bmrequest.cpp385
-rw-r--r--src/bm/bmrequest.h28
-rw-r--r--src/bm/index.cpp76
-rw-r--r--src/bm/index.h14
-rw-r--r--src/bm/plotter.cpp2
-rw-r--r--src/bmclient/main.cpp107
-rw-r--r--src/bmweb/indexsection.js64
7 files changed, 68 insertions, 608 deletions
diff --git a/src/bm/bmrequest.cpp b/src/bm/bmrequest.cpp
index 8781c8e..7921bb0 100644
--- a/src/bm/bmrequest.cpp
+++ b/src/bm/bmrequest.cpp
@@ -4847,13 +4847,9 @@ QByteArray BMRequest_IndexGetValues::toRequestBuffer(QString *)
{
QString request =
QString(
- "<request type=\"%1\"><args evalLoTime=\"%2\" evalHiTime=\"%3\" evalStep=\"%4\" "
- "baseTimestamp=\"%5\" medianWinSize=\"%6\" cacheKey=\"%7\" />")
- .arg(name()).arg(evalLoTime).arg(evalHiTime).arg(evalStep).arg(baseTimestamp)
- .arg(medianWinSize).arg(cacheKey);
-
- for (int i = 0; i < evalTimestamps.size(); ++i)
- request += QString("<evalTimestamp value=\"%1\" />").arg(evalTimestamps.at(i));
+ "<request type=\"%1\"><args baseTimestamp=\"%2\" medianWinSize=\"%3\" "
+ "cacheKey=\"%4\" />")
+ .arg(name()).arg(baseTimestamp).arg(medianWinSize).arg(cacheKey);
for (int i = 0; i < testCaseFilter.size(); ++i)
request += QString("<testCase name=\"%1\" />").arg(testCaseFilter.at(i));
@@ -4875,306 +4871,6 @@ QByteArray BMRequest_IndexGetValues::toRequestBuffer(QString *)
return xmlConvert(request);
}
-// ### OBSOLETE!
-void BMRequest_IndexGetValues::computeIndexValues(
- const QList<ResultHistoryInfo *> &rhInfos, int baseTimestamp, const QList<int> &evalTimestamps,
- int medianWinSize, const QList<qreal> &baseDistSums, qreal minBaseDistSum,
- qreal maxBaseDistSum, bool debugPrint, QString *reply)
-{
- // --- BEGIN preparation -------------------------------------------------------------
-
- QList<qreal> initWeights;
-#if 0
- // Set up initial weights for each evaluation timestamp as base time proximity weights
- // (i.e. the closer the contributing results of this result history are to the base
- // timestamp, the higher the weight) ...
- for (int i = 0; i < rhInfos.size(); ++i) {
- const qreal invBaseDistSum = (minBaseDistSum + maxBaseDistSum) - baseDistSums.at(i);
- Q_ASSERT(invBaseDistSum >= minBaseDistSum);
- Q_ASSERT(invBaseDistSum <= maxBaseDistSum);
- initWeights.append(invBaseDistSum);
- }
-#else
- // Alternatively, the initial weights could all be equal
- // (a special case that expresses the arithmetic mean):
- Q_UNUSED(baseDistSums);
- Q_UNUSED(minBaseDistSum);
- Q_UNUSED(maxBaseDistSum);
- for (int i = 0; i < rhInfos.size(); ++i)
- initWeights.append(1.0);
-#endif
- bool ok = BMMisc::normalize(initWeights); // renormalize
- Q_ASSERT(ok); // ### 4 NOW
-
-
- // --- BEGIN trend preparation -------------------------------------------------------------
-
-#if 0
-
- // (4 TESTING) Compute trend values (based on simple linear regression of the median-smoothed
- // time series) ...
- if (debugPrint)
- fprintf(stderr, "computing trend values (for testing) ... ");
- QList<qreal> trends;
- QList<qreal> validTrends;
- qreal trendSum = 0.0;
- qreal validTrendSum = 0.0;
- for (int i = 0; i < rhInfos.size(); ++i) {
- ResultHistoryInfo *rhInfo = rhInfos.at(i);
- QList<qreal> smoothValues;
- if (rhInfo->getSmoothValues(medianWinSize, &smoothValues)) {
-
- // compute simple linear regression ...
-
- QList<int> timestamps = rhInfo->timestamps();
- Q_ASSERT(smoothValues.size() == timestamps.size());
-
- QVector<qreal> t(timestamps.size());
- for (int j = 0; j < timestamps.size(); ++j)
- t.replace(j, static_cast<qreal>(timestamps.at(j)));
- QVector<qreal> v = QVector<qreal>::fromList(smoothValues);
-
- qreal a = 0.0;
- qreal b = 0.0;
- if (computeSimpleLinearRegression(t, v, &a, &b)) {
- const qreal trend = BMMisc::lowerIsBetter(rhInfo->metric()) ? -b : b;
- trends.append(trend);
- trendSum += trend;
- validTrends.append(trend);
- validTrendSum += trend;
- } else {
- trends.append(0.0);
- }
- } else {
- trends.append(0.0);
- }
- }
-
- if (debugPrint)
- fprintf(stderr, "sorting ... ");
- QList<qreal> sortedTrends(trends);
- qSort(sortedTrends);
- QList<qreal> sortedValidTrends(validTrends);
- qSort(sortedValidTrends);
- if (debugPrint)
- fprintf(stderr, "done\n");
-
- // Print statistics for all trends and valid trends ...
- if (debugPrint) {
- fprintf(stderr, "\n--- BEGIN trend statistics (higher is better) ---\n");
- fprintf(
- stderr, "%s\n",
- QString(" all trends - count: %1; mean: %2; median: %3")
- .arg(sortedTrends.size())
- .arg(sortedTrends.isEmpty()
- ? QString("n/a")
- : QString("%1").arg(trendSum / sortedTrends.size()))
- .arg(sortedTrends.isEmpty()
- ? QString("n/a")
- : QString("%1").arg(sortedTrends.at(sortedTrends.size() / 2)))
- .toLatin1().data()
- );
- fprintf(
- stderr, "%s\n",
- QString("valid trends - count: %1; mean: %2; median: %3")
- .arg(sortedValidTrends.size())
- .arg(sortedValidTrends.isEmpty()
- ? QString("n/a")
- : QString("%1").arg(validTrendSum / sortedValidTrends.size()))
- .arg(sortedValidTrends.isEmpty()
- ? QString("n/a")
- : QString("%1").arg(sortedValidTrends.at(sortedValidTrends.size() / 2)))
- .toLatin1().data()
- );
- fprintf(stderr, "--- END trend statistics ---\n\n");
- }
-
- // Define percentile values (used for cheating!) ...
- const qreal trend0999percentile =
- sortedTrends.at(static_cast<int>(0.999 * sortedTrends.size()));
- const qreal trend099percentile = sortedTrends.at(static_cast<int>(0.99 * sortedTrends.size()));
- const qreal trend095percentile = sortedTrends.at(static_cast<int>(0.95 * sortedTrends.size()));
- const qreal trend090percentile = sortedTrends.at(static_cast<int>(0.9 * sortedTrends.size()));
- const qreal trend075percentile = sortedTrends.at(static_cast<int>(0.75 * sortedTrends.size()));
- const qreal trend050percentile = sortedTrends.at(static_cast<int>(0.5 * sortedTrends.size()));
- const qreal trend025percentile = sortedTrends.at(static_cast<int>(0.25 * sortedTrends.size()));
- const qreal trend010percentile = sortedTrends.at(static_cast<int>(0.1 * sortedTrends.size()));
- const qreal trend005percentile = sortedTrends.at(static_cast<int>(0.05 * sortedTrends.size()));
- const qreal trend001percentile = sortedTrends.at(static_cast<int>(0.01 * sortedTrends.size()));
- const qreal trend0001percentile =
- sortedTrends.at(static_cast<int>(0.001 * sortedTrends.size()));
-
- // --- END trend preparation -------------------------------------------------------------
-
-
- // --- BEGIN size preparation -------------------------------------------------------------
-
- // (4 TESTING) Register result history sizes ...
- if (debugPrint)
- fprintf(stderr, "registering result history sizes (for testing) ... ");
- QList<qreal> sizes;
- qreal sizeSum = 0.0;
- qreal minSize = -1.0;
- qreal maxSize = -1.0;
- for (int i = 0; i < rhInfos.size(); ++i) {
- ResultHistoryInfo *rhInfo = rhInfos.at(i);
- const qreal size = static_cast<qreal>(rhInfo->size());
- sizes.append(size);
- sizeSum += size;
- if (i == 0) {
- minSize = maxSize = size;
- } else {
- minSize = qMin(minSize, size);
- maxSize = qMax(maxSize, size);
- }
- }
-
- if (debugPrint)
- fprintf(stderr, "sorting ... ");
- QList<qreal> sortedSizes(sizes);
- qSort(sortedSizes);
- if (debugPrint)
- fprintf(stderr, "done\n");
-
- // Print size statistics ...
- if (debugPrint) {
- fprintf(stderr, "\n--- BEGIN size statistics ---\n");
- fprintf(
- stderr, "%s\n",
- QString("sizes: count: %1; min: %2; max: %3; mean: %4; median: %5")
- .arg(sortedSizes.size())
- .arg(minSize)
- .arg(maxSize)
- .arg(sortedSizes.isEmpty()
- ? QString("n/a")
- : QString("%1").arg(sizeSum / sortedSizes.size()))
- .arg(sortedSizes.isEmpty()
- ? QString("n/a")
- : QString("%1").arg(sortedSizes.at(sortedSizes.size() / 2)))
- .toLatin1().data()
- );
- fprintf(stderr, "--- END size statistics ---\n\n");
- }
-
- // Define percentile values ...
- const qreal size0999percentile = sortedSizes.at(static_cast<int>(0.999 * sortedSizes.size()));
- const qreal size099percentile = sortedSizes.at(static_cast<int>(0.99 * sortedSizes.size()));
- const qreal size095percentile = sortedSizes.at(static_cast<int>(0.95 * sortedSizes.size()));
- const qreal size090percentile = sortedSizes.at(static_cast<int>(0.9 * sortedSizes.size()));
- const qreal size075percentile = sortedSizes.at(static_cast<int>(0.75 * sortedSizes.size()));
- const qreal size050percentile = sortedSizes.at(static_cast<int>(0.5 * sortedSizes.size()));
- const qreal size025percentile = sortedSizes.at(static_cast<int>(0.25 * sortedSizes.size()));
- const qreal size010percentile = sortedSizes.at(static_cast<int>(0.1 * sortedSizes.size()));
- const qreal size005percentile = sortedSizes.at(static_cast<int>(0.05 * sortedSizes.size()));
- const qreal size001percentile = sortedSizes.at(static_cast<int>(0.01 * sortedSizes.size()));
- const qreal size0001percentile = sortedSizes.at(static_cast<int>(0.001 * sortedSizes.size()));
-
-#endif
-
- // --- END size preparation -------------------------------------------------------------
-
- // --- END preparation -------------------------------------------------------------
-
-
- // Loop over evaluation timestamps ...
- for (int i = 0; i < evalTimestamps.size(); ++i) {
-
- if (!(i % qMax(1, (evalTimestamps.size() / 20)))) {
- if (debugPrint)
- fprintf(
- stderr, "computing index values (%0.0f%% done)\r",
- 100 * (qreal(i) / evalTimestamps.size()));
- }
-
- QList<qreal> diffs; // initial (unweighted) differences
- QList<qreal> weights; // weights (accumulated and normalized)
- QList<qreal> distSums; // sums of distances to values contributing to evaluation timestamp
- qreal minDistSum = -1.0;
- qreal maxDistSum = -1.0;
- QList<int> contr; // indexes of result histories that contribute to this timestamp
-
- // Compute initial values ...
- for (int j = 0; j < rhInfos.size(); ++j) {
- ResultHistoryInfo *rhInfo = rhInfos.at(j);
-
- // --- BEGIN cheating ---
- // Skip if trend is not among the 25 % best ...
- // if (trends.at(j) < trend075percentile)
- // continue;
- // --- END cheating ---
-
- // Skip if size is not among the 50 % largest ...
- // if (sizes.at(j) < size050percentile)
- // continue;
-
- int targetPos = -1;
- qreal distSum = -1.0;
- if (rhInfo->getSmoothPos(
- evalTimestamps.at(i), medianWinSize, &targetPos, false, &distSum)) {
-
- const qreal targetVal = rhInfo->value(targetPos);
-
- int basePos = -1;
- ok = rhInfo->getSmoothPos(baseTimestamp, medianWinSize, &basePos, true);
- Q_ASSERT(ok);
-
- const qreal baseVal = rhInfo->value(basePos);
-
- const qreal diff = BMMisc::log2diff(targetVal, baseVal, rhInfo->metric());
- diffs.append(diff);
- contr.append(j);
-
- distSums.append(distSum);
- if (j == 0) {
- minDistSum = maxDistSum = distSum;
- } else {
- minDistSum = qMin(minDistSum, distSum);
- maxDistSum = qMax(maxDistSum, distSum);
- }
- }
- }
-
- qreal indexValue = -1.0;
-
- if (!contr.isEmpty()) {
-
- // Initialize weights ...
- for (int j = 0; j < contr.size(); ++j)
- weights.append(initWeights.at(contr.at(j)));
-
- // Apply evaluation time proximity weights (i.e. the closer the contributing results
- // of this result history are to the evaluation timestamp, the higher the weight) ...
- for (int j = 0; j < contr.size(); ++j) {
- const qreal invDistSum = (minDistSum + maxDistSum) - distSums.at(j);
- Q_ASSERT(invDistSum >= minDistSum);
- Q_ASSERT(invDistSum <= maxDistSum);
- weights[j] *= invDistSum;
- }
- ok = BMMisc::normalize(weights); // renormalize
- Q_ASSERT(ok); // ### 4 NOW
-
-
- // Compute the final index value as the accumulated weighted average of the
- // initial differences ...
- qreal wavg = 0.0;
- for (int j = 0; j < diffs.size(); ++j)
- wavg += (weights.at(j) * diffs.at(j));
- indexValue = wavg;
-
- }
-
- reply->append(
- QString("<value timestamp=\"%1\" indexValue=\"%2\" contributions=\"%3\" />")
- .arg(evalTimestamps.at(i))
- .arg(indexValue)
- .arg(contr.size()));
-
- }
-
- if (debugPrint)
- fprintf(stderr, "computing index values (100%% done)\n");
-}
-
QByteArray BMRequest_IndexGetValues::toReplyBuffer()
{
QDomElement argsElem = doc.elementsByTagName("args").at(0).toElement();
@@ -5207,55 +4903,11 @@ QByteArray BMRequest_IndexGetValues::toReplyBuffer()
if (debugPrint)
fprintf(stderr, "computing from scratch ...\n");
- // Get evaluation timestamps ...
- QDomNodeList evalTimestampNodes = doc.elementsByTagName("evalTimestamp");
- const int currTimestamp = QDateTime::currentDateTime().toTime_t();
- if (evalTimestampNodes.size() == 0) {
- // .. compute from time range ...
-
- evalLoTime = argsElem.attributeNode("evalLoTime").value().toInt(&ok);
- Q_ASSERT(ok);
- evalHiTime = argsElem.attributeNode("evalHiTime").value().toInt(&ok);
- Q_ASSERT(ok);
- evalStep = argsElem.attributeNode("evalStep").value().toInt(&ok);
- Q_ASSERT(ok);
-
- Q_ASSERT(evalLoTime >= 0);
- Q_ASSERT((evalLoTime <= evalHiTime) || (evalHiTime == -1));
- Q_ASSERT(evalStep > 0);
-
- if (evalHiTime == -1)
- evalHiTime = currTimestamp;
-
- for (int t = evalLoTime; t <= evalHiTime; t += evalStep)
- evalTimestamps.append(t);
- if ((evalHiTime - evalLoTime) % evalStep)
- evalTimestamps.append(evalHiTime);
-
- } else {
- // ... use explicit timestamps ...
-
- bool currTimeRequested = false;
- for (int i = 0; i < evalTimestampNodes.size(); ++i) {
- const int evalTimestamp =
- evalTimestampNodes.at(i).toElement().attributeNode("value").value().toInt(&ok);
- Q_ASSERT(ok);
- if ((evalTimestamp == -1) || (evalTimestamp > currTimestamp)) {
- currTimeRequested = true;
- } else {
- evalTimestamps.append(evalTimestamp);
- }
- }
-
- if (currTimeRequested)
- evalTimestamps.append(currTimestamp);
- }
-
// Get base timestamp ...
baseTimestamp = argsElem.attributeNode("baseTimestamp").value().toInt(&ok);
Q_ASSERT(ok);
if (baseTimestamp == -1)
- baseTimestamp = currTimestamp;
+ baseTimestamp = QDateTime::currentDateTime().toTime_t();
// Get median window size ...
medianWinSize = argsElem.attributeNode("medianWinSize").value().toInt(&ok);
@@ -5423,14 +5075,16 @@ QByteArray BMRequest_IndexGetValues::toReplyBuffer()
// Candidate result histories exist, so compute index values ...
+ QList<int> evalTimestamps;
IndexAlgorithm1 index(
- rhInfos, baseTimestamp, evalTimestamps, medianWinSize, &nonPositiveRH);
+ rhInfos, baseTimestamp, medianWinSize, &evalTimestamps, &nonPositiveRH);
if (!index.isValid()) {
return xmlConvert(
errorReply(
name(), QString("failed to compute index (1): %1").arg(index.invalidReason())));
}
+
QList<qreal> indexValues;
QList<int> contrCounts;
QList<QList<Index::RankedInfo> > topContr;
@@ -5559,6 +5213,12 @@ void BMRequest_IndexGetValues::handleReply_HTML(const QStringList &args) const
reply += "<br /><br />";
+ reply += "The index is evaluated at each of the timestamps for which a result exist for ";
+ reply += "at least one of the contributing result histories (it is only at these timestamps ";
+ reply += "the index value may potentially change).";
+
+ reply += "<br /><br />";
+
reply += "The <u>change</u> in index value between any two points in time indicates the ";
reply += "average performance increase during this time period in terms of a ";
reply += "<u>log2</u>-based difference. ";
@@ -6227,13 +5887,9 @@ QByteArray BMRequest_IndexPutConfig::toRequestBuffer(QString *)
// Non-filter values ...
request += QString(
- "<args configName=\"%1\" baseTimestamp=\"%2\" evalLoTime=\"%3\" "
- "evalHiTime=\"%4\" evalStep=\"%5\" medianWinSize=\"%6\" />")
+ "<args configName=\"%1\" baseTimestamp=\"%2\" medianWinSize=\"%3\" />")
.arg(configName)
.arg(baseTimestamp)
- .arg(evalLoTime)
- .arg(evalHiTime)
- .arg(evalStep)
.arg(medianWinSize);
// Filter values ...
@@ -6299,15 +5955,6 @@ QByteArray BMRequest_IndexPutConfig::toReplyBuffer()
baseTimestamp = argsElem.attributeNode("baseTimestamp").value().toInt(&ok);
Q_ASSERT(ok);
- evalLoTime = argsElem.attributeNode("evalLoTime").value().toInt(&ok);
- Q_ASSERT(ok);
-
- evalHiTime = argsElem.attributeNode("evalHiTime").value().toInt(&ok);
- Q_ASSERT(ok);
-
- evalStep = argsElem.attributeNode("evalStep").value().toInt(&ok);
- Q_ASSERT(ok);
-
medianWinSize = argsElem.attributeNode("medianWinSize").value().toInt(&ok);
Q_ASSERT(ok);
@@ -6381,9 +6028,7 @@ QByteArray BMRequest_IndexPutConfig::toReplyBuffer()
"VALUES ('%1', %2, %3, %4, %5, %6);")
.arg(configName)
.arg(baseTimestamp)
- .arg(evalLoTime)
- .arg(evalHiTime)
- .arg(evalStep)
+ .arg(-1).arg(-1).arg(-1) // ### obsolete, so use dummy values for now
.arg(medianWinSize))) {
reply = errorReply(*query, name(), "failed to insert into indexConfig");
deleteQuery(query, Rollback);
diff --git a/src/bm/bmrequest.h b/src/bm/bmrequest.h
index 0732778..89c50f3 100644
--- a/src/bm/bmrequest.h
+++ b/src/bm/bmrequest.h
@@ -565,24 +565,17 @@ class BMRequest_IndexGetValues : public BMRequest
{
public:
BMRequest_IndexGetValues(
- const int evalLoTime, const int evalHiTime, const int evalStep,
- const QList<int> &evalTimestamps, const int baseTimestamp, const int medianWinSize,
+ const int baseTimestamp, const int medianWinSize,
const QString &cacheKey, const QStringList &testCaseFilter,
const QStringList &metricFilter, const QStringList &platformFilter,
const QStringList &hostFilter, const QStringList &branchFilter)
- : evalLoTime(evalLoTime), evalHiTime(evalHiTime), evalStep(evalStep)
- , evalTimestamps(evalTimestamps), baseTimestamp(baseTimestamp)
- , medianWinSize(medianWinSize), cacheKey(cacheKey), testCaseFilter(testCaseFilter)
- , metricFilter(metricFilter), platformFilter(platformFilter), hostFilter(hostFilter)
- , branchFilter(branchFilter)
+ : baseTimestamp(baseTimestamp), medianWinSize(medianWinSize), cacheKey(cacheKey)
+ , testCaseFilter(testCaseFilter), metricFilter(metricFilter)
+ , platformFilter(platformFilter), hostFilter(hostFilter), branchFilter(branchFilter)
{}
BMRequest_IndexGetValues(const QDomDocument &doc) : BMRequest(doc) {}
private:
- mutable int evalLoTime;
- mutable int evalHiTime;
- mutable int evalStep;
- mutable QList<int> evalTimestamps;
mutable int baseTimestamp;
mutable int medianWinSize;
QString cacheKey;
@@ -600,10 +593,6 @@ private:
void handleReply_HTML(const QStringList &args) const;
void handleReply_Image(const QStringList &args) const;
- static void computeIndexValues(
- const QList<ResultHistoryInfo *> &rhInfos, int baseTimestamp,
- const QList<int> &evalTimestamps, int medianWinSize, const QList<qreal> &baseDistSums,
- qreal minBaseDistSum, qreal maxBaseDistSum, bool debugPrint, QString *reply);
static void appendToFilterTable(
const QStringList &filter, const QString &filterName, QString *reply);
};
@@ -644,13 +633,11 @@ class BMRequest_IndexPutConfig : public BMRequest
{
public:
BMRequest_IndexPutConfig(
- const QString &configName, const int baseTimestamp, const int evalLoTime,
- const int evalHiTime, const int evalStep, const int medianWinSize,
+ const QString &configName, const int baseTimestamp, const int medianWinSize,
const QStringList &testCaseFilter, const QStringList &metricFilter,
const QStringList &platformFilter, const QStringList &hostFilter,
const QStringList &branchFilter)
- : configName(configName), baseTimestamp(baseTimestamp), evalLoTime(evalLoTime)
- , evalHiTime(evalHiTime), evalStep(evalStep), medianWinSize(medianWinSize)
+ : configName(configName), baseTimestamp(baseTimestamp), medianWinSize(medianWinSize)
, testCaseFilter(testCaseFilter), metricFilter(metricFilter)
, platformFilter(platformFilter), hostFilter(hostFilter), branchFilter(branchFilter)
{}
@@ -659,9 +646,6 @@ public:
private:
QString configName;
int baseTimestamp;
- int evalLoTime;
- int evalHiTime;
- int evalStep;
int medianWinSize;
QStringList testCaseFilter;
QStringList metricFilter;
diff --git a/src/bm/index.cpp b/src/bm/index.cpp
index c80a9bd..afb5ab1 100644
--- a/src/bm/index.cpp
+++ b/src/bm/index.cpp
@@ -32,11 +32,11 @@
// Note: The dynamic memory in \a candidateRHInfos is deleted by this class.
Index::Index(
const QList<ResultHistoryInfo *> &candidateRHInfos, const int baseTimestamp,
- const QList<int> &evalTimestamps, int medianWinSize, int *rejectedNonPositive)
- : baseTimestamp(baseTimestamp), evalTimestamps(evalTimestamps)
- , medianWinSize(medianWinSize), valid(false), invalidReason_("uninitialized")
+ int medianWinSize, QList<int> *evalTimestamps, int *rejectedNonPositive)
+ : baseTimestamp(baseTimestamp), medianWinSize(medianWinSize), valid(false)
+ , invalidReason_("uninitialized")
{
- init(candidateRHInfos, rejectedNonPositive);
+ init(candidateRHInfos, evalTimestamps, rejectedNonPositive);
}
Index::~Index()
@@ -47,7 +47,9 @@ Index::~Index()
}
// ### 2 B DOCUMENTED!
-void Index::init(const QList<ResultHistoryInfo *> &candidateRHInfos, int *rejectedNonPositive)
+void Index::init(
+ const QList<ResultHistoryInfo *> &candidateRHInfos, QList<int> *evalTimestamps,
+ int *rejectedNonPositive)
{
if (baseTimestamp < 0) {
valid = false;
@@ -55,47 +57,24 @@ void Index::init(const QList<ResultHistoryInfo *> &candidateRHInfos, int *reject
return;
}
- for (int i = 1; i < evalTimestamps.size(); ++i) {
- if (evalTimestamps.at(i - 1) > evalTimestamps.at(i)) {
- valid = false;
- invalidReason_ = "non-increasing eval timestamp order";
- return;
- }
- }
-
- if (evalTimestamps.first() < 0) {
- valid = false;
- invalidReason_ = "negative eval timestamp";
- return;
- }
-
- populateRHInfos(candidateRHInfos, rejectedNonPositive);
- if (rhInfos.isEmpty()) {
- valid = false;
- invalidReason_ = "no valid result histories";
- return;
- }
-
- valid = true;
- invalidReason_ = "";
-}
-
-// Populates rhInfos from \a candidateRHInfos by rejecting certain result histories.
-void Index::populateRHInfos(
- const QList<ResultHistoryInfo *> &candidateRHInfos, int *rejectedNonPositive)
-{
+
int rejectedNonPositive_ = 0;
+ QSet<int> etset;
for (int i = 0; i < candidateRHInfos.size(); ++i) {
ResultHistoryInfo *rhInfo = candidateRHInfos.at(i);
Q_ASSERT(rhInfo->size() > 0);
- // Reject candidate if the time series contains at least one non-positive value ...
int j = 0;
for (; j < rhInfo->size(); ++j) {
+
+ // Reject candidate if the time series contains at least one non-positive value ...
if (rhInfo->value(j) <= 0.0)
break;
+
+ // Expand union of eval timestamps ...
+ etset.insert(rhInfo->timestamp(j));
}
if (j < rhInfo->size()) {
delete rhInfo;
@@ -109,6 +88,19 @@ void Index::populateRHInfos(
if (rejectedNonPositive)
*rejectedNonPositive = rejectedNonPositive_;
+
+ if (rhInfos.isEmpty()) {
+ valid = false;
+ invalidReason_ = "no valid result histories";
+ return;
+ }
+
+ *evalTimestamps = etset.toList();
+ qSort(*evalTimestamps);
+ evalTimestamps_ = *evalTimestamps;
+
+ valid = true;
+ invalidReason_ = "";
}
@@ -146,16 +138,16 @@ bool IndexAlgorithm1::computeValues(
*baseValuePos = -1;
// Loop over evaluation timestamps ...
- for (int i = 0; i < evalTimestamps.size(); ++i) {
+ for (int i = 0; i < evalTimestamps_.size(); ++i) {
if (*baseValuePos == -1) {
// Determine if this evaluation timestamp represents the base timestamp ...
- if (baseTimestamp < evalTimestamps.first()) {
+ if (baseTimestamp < evalTimestamps_.first()) {
*baseValuePos = 0;
- } else if (((i < (evalTimestamps.size() - 1))
- && (baseTimestamp >= evalTimestamps.at(i))
- && (baseTimestamp < evalTimestamps.at(i + 1)))
- || (i == (evalTimestamps.size() - 1)))
+ } else if (((i < (evalTimestamps_.size() - 1))
+ && (baseTimestamp >= evalTimestamps_.at(i))
+ && (baseTimestamp < evalTimestamps_.at(i + 1)))
+ || (i == (evalTimestamps_.size() - 1)))
*baseValuePos = i;
}
@@ -180,7 +172,7 @@ bool IndexAlgorithm1::computeValues(
// Attempt to sample the result history at this timestamp ...
int targetPos = -1;
- if (rhInfo->getSmoothPos(evalTimestamps.at(i), medianWinSize, &targetPos)) {
+ if (rhInfo->getSmoothPos(evalTimestamps_.at(i), medianWinSize, &targetPos)) {
const qreal targetVal = rhInfo->value(targetPos);
diff --git a/src/bm/index.h b/src/bm/index.h
index 75cf85c..a181a7f 100644
--- a/src/bm/index.h
+++ b/src/bm/index.h
@@ -33,7 +33,7 @@ class Index {
public:
Index(
const QList<ResultHistoryInfo *> &candidateRHInfos, const int baseTimestamp,
- const QList<int> &evalTimestamps, int medianWinSize, int *rejectedNonPositive = 0);
+ int medianWinSize, QList<int> *evalTimestamps, int *rejectedNonPositive = 0);
virtual ~Index();
bool isValid() const { return valid; }
@@ -66,7 +66,7 @@ public:
protected:
QList<ResultHistoryInfo *> rhInfos;
int baseTimestamp;
- QList<int> evalTimestamps;
+ QList<int> evalTimestamps_;
int medianWinSize;
private:
@@ -74,9 +74,8 @@ private:
QString invalidReason_;
void init(
- const QList<ResultHistoryInfo *> &candidateRHInfos, int *rejectedNonPositive = 0);
- void populateRHInfos(
- const QList<ResultHistoryInfo *> &candidateRHInfos, int *rejectedNonPositive = 0);
+ const QList<ResultHistoryInfo *> &candidateRHInfos, QList<int> *evalTimestamps,
+ int *rejectedNonPositive = 0);
};
// ### 2 B DOCUMENTED!
@@ -84,9 +83,8 @@ class IndexAlgorithm1 : public Index {
public:
IndexAlgorithm1(
const QList<ResultHistoryInfo *> &candidateRHInfos, const int baseTimestamp,
- const QList<int> &evalTimestamps, int medianWinSize, int *rejectedNonPositive = 0)
- : Index(
- candidateRHInfos, baseTimestamp, evalTimestamps, medianWinSize, rejectedNonPositive)
+ int medianWinSize, QList<int> *evalTimestamps, int *rejectedNonPositive = 0)
+ : Index(candidateRHInfos, baseTimestamp, medianWinSize, evalTimestamps, rejectedNonPositive)
{}
bool computeValues(
diff --git a/src/bm/plotter.cpp b/src/bm/plotter.cpp
index 0430b90..e2ce934 100644
--- a/src/bm/plotter.cpp
+++ b/src/bm/plotter.cpp
@@ -551,7 +551,7 @@ bool IndexPlotter::drawScenes(
const QColor color(0, 0, 0, 255);
scene_near->addPath(path, QPen(color), QBrush(color));
const QColor missingColor(255, 0, 0, 255);
- scene_near->addPath(missingPath, QPen(missingColor, 1), QBrush(missingColor));
+ scene_near->addPath(missingPath, QPen(missingColor, 2), QBrush(missingColor));
}
// Draw labels ...
diff --git a/src/bmclient/main.cpp b/src/bmclient/main.cpp
index 745f799..738e734 100644
--- a/src/bmclient/main.cpp
+++ b/src/bmclient/main.cpp
@@ -978,75 +978,6 @@ BMRequest * Executor::createIndexGetValuesRequest(
QStringList values;
- // Get explicit eval timestamps or time range ...
- int evalLoTime = -1;
- int evalHiTime = -1;
- int evalStep = -1;
- QList<int> evalTimestamps;
-
- if (BMMisc::hasOption(args, "-evaltimestamp") && BMMisc::hasOption(args, "-evaltimerange")) {
- *error = "-evaltimestamp and -evaltimerange options are mutually exclusive";
- return 0;
- }
- if (BMMisc::hasOption(args, "-evaltimestamp")) {
- for (int i = 0;; ++i) {
- if (BMMisc::getOption(args, "-evaltimestamp", &values, 1, i, error)) {
- bool ok;
- const int evalTimestamp = values.first().toInt(&ok);
- if (!ok) {
- *error =
- QString("eval timestamp %1 not an integer: %2").arg(i).arg(values.first());
- return 0;
- }
- evalTimestamps.append(qMax(evalTimestamp, -1)); // -1 is current time
- } else {
- if (!error->isEmpty())
- return 0;
- break;
- }
- }
-
- Q_ASSERT(!evalTimestamps.isEmpty());
-
- // Remove duplicates from and sort eval timestamps in ascending order ...
- evalTimestamps = evalTimestamps.toSet().toList();
- qSort(evalTimestamps);
-
- } else if (BMMisc::hasOption(args, "-evaltimerange")) {
-
- if (BMMisc::getOption(args, "-evaltimerange", &values, 3, 0, error)) {
- bool ok;
- evalLoTime = values.at(0).toInt(&ok);
- if (!ok) {
- *error = QString("eval time range start not an integer: %1").arg(values.at(0));
- return 0;
- }
- evalHiTime = values.at(1).toInt(&ok);
- if (!ok) {
- *error = QString("eval time range end not an integer: %1").arg(values.at(1));
- return 0;
- }
- evalStep = values.at(2).toInt(&ok);
- if ((!ok) || (evalStep < 1)) {
- *error =
- QString("eval time range step not a positive integer: %1").arg(values.at(2));
- return 0;
- }
-
- if ((evalLoTime < 0) || ((evalLoTime > evalHiTime) && (evalHiTime != -1))) {
- *error = QString("invalid time range: %1..%2").arg(evalLoTime).arg(evalHiTime);
- return 0;
- }
-
- } else {
- return 0;
- }
- } else {
-
- *error = "failed to find -evaltimestamp or -evaltimerange options";
- return 0;
- }
-
// Get base timestamp ...
int baseTimestamp = -1; // default is current time
if (BMMisc::getOption(args, "-basetimestamp", &values, 1, 0, error)) {
@@ -1106,8 +1037,8 @@ BMRequest * Executor::createIndexGetValuesRequest(
return 0;
return new BMRequest_IndexGetValues(
- evalLoTime, evalHiTime, evalStep, evalTimestamps, baseTimestamp, medianWinSize, cacheKey,
- testCaseFilter, metricFilter, platformFilter, hostFilter, branchFilter);
+ baseTimestamp, medianWinSize, cacheKey, testCaseFilter, metricFilter, platformFilter,
+ hostFilter, branchFilter);
}
BMRequest * Executor::createIndexPutConfigRequest(const QStringList &args, QString *error) const
@@ -1140,32 +1071,6 @@ BMRequest * Executor::createIndexPutConfigRequest(const QStringList &args, QStri
}
baseTimestamp = qMax(baseTimestamp, -1);
- // Get evaluation time range ...
- if (!BMMisc::getOption(args, "-evaltimerange", &values, 3, 0, error)) {
- if (error->isEmpty())
- *error = "-evaltimerange option not found";
- return 0;
- }
- const int evalLoTime = values.at(0).toInt(&ok);
- if (!ok) {
- *error = QString("eval time range start not an integer: %1").arg(values.at(0));
- return 0;
- }
- const int evalHiTime = values.at(1).toInt(&ok);
- if (!ok) {
- *error = QString("eval time range end not an integer: %1").arg(values.at(1));
- return 0;
- }
- const int evalStep = values.at(2).toInt(&ok);
- if ((!ok) || (evalStep < 1)) {
- *error = QString("eval time range step not a positive integer: %1").arg(values.at(2));
- return 0;
- }
- if ((evalLoTime < 0) || ((evalLoTime > evalHiTime) && (evalHiTime != -1))) {
- *error = QString("invalid time range: %1..%2").arg(evalLoTime).arg(evalHiTime);
- return 0;
- }
-
// Get median window size ...
if (!BMMisc::getOption(args, "-medianwinsize", &values, 1, 0, error)) {
if (error->isEmpty())
@@ -1196,8 +1101,8 @@ BMRequest * Executor::createIndexPutConfigRequest(const QStringList &args, QStri
return 0;
return new BMRequest_IndexPutConfig(
- configName, baseTimestamp, evalLoTime, evalHiTime, evalStep, medianWinSize, testCaseFilter,
- metricFilter, platformFilter, hostFilter, branchFilter);
+ configName, baseTimestamp, medianWinSize, testCaseFilter, metricFilter, platformFilter,
+ hostFilter, branchFilter);
}
BMRequest * Executor::createGetHistoriesRequest(const QStringList &args, QString *error) const
@@ -1674,7 +1579,6 @@ class DirectExecutor : public Executor
<<
"index get values \\\n"
- " {-evaltimestamp <...> ...} | {-evaltimerange <first> <last> <step>} \\\n"
" -basetimestamp <...> [-medianwinsize <...> (default = 8)] \\\n"
" [-testcase <...> -testcase <...> ...] [-metric <...> -metric <...> ...] \\\n"
" [-platform <...> -platform <...> ...] [-host <...> -host <...> ...] \\\n"
@@ -1696,8 +1600,7 @@ class DirectExecutor : public Executor
<<
"index put config -name <...> \\\n"
- " -basetimestamp <...> -evaltimerange <first> <last> <step> \\\n"
- " -medianwinsize <...> \\\n"
+ " -basetimestamp <...> -medianwinsize <...> \\\n"
" [-testcase <...> -testcase <...> ...] [-metric <...> -metric <...> ...] \\\n"
" [-platform <...> -platform <...> ...] [-host <...> -host <...> ...] \\\n"
" [-branch <...> -branch <...> ...]\n"
diff --git a/src/bmweb/indexsection.js b/src/bmweb/indexsection.js
index 93f3630..ede6923 100644
--- a/src/bmweb/indexsection.js
+++ b/src/bmweb/indexsection.js
@@ -21,9 +21,7 @@
**
****************************************************************************/
-function updateEvalLink(
- defaultBaseTime, defaultEvalTimeLo, defaultEvalTimeHi, defaultEvalTimeStep,
- defaultMedianWinSize)
+function updateEvalLink(defaultBaseTime, defaultMedianWinSize)
{
// Initialize URL ...
url = "http://" + location.host + "/cgi-bin/bmclientwrapper";
@@ -40,23 +38,6 @@ function updateEvalLink(
url += " -basetimestamp " + baseTime;
- // Add evaluation timestamps ...
- evalTimeLo = getIntFromTextInput("ixEvalLoTime", defaultEvalTimeLo);
- document.getElementById("ixEvalLoTime").value = evalTimeLo;
-
- evalTimeHi = getIntFromTextInput("ixEvalHiTime", defaultEvalTimeHi);
- document.getElementById("ixEvalHiTime").value = evalTimeHi;
-
- evalTimeStep = getIntFromTextInput("ixEvalStep", defaultEvalTimeStep);
- // Make sure the time step is at least 24 hours to prevent unnecessary
- // server load (results are currently not uploaded to the server more
- // than approximately once a day anyway) ...
- evalTimeStep = Math.max(evalTimeStep, 86400);
- document.getElementById("ixEvalStep").value = evalTimeStep;
-
- url += " -evaltimerange " + evalTimeLo + " " + evalTimeHi + " " + evalTimeStep;
-
-
// Add median window size ...
medianWinSize = getIntFromTextInput("ixMedianWinSize", defaultMedianWinSize);
document.getElementById("ixMedianWinSize").value = medianWinSize;
@@ -96,9 +77,6 @@ function updateEvalLink(
function IndexSection()
{
var defaultBaseTime = -1; // current time
- var defaultEvalTimeLo = 1259668800; // 1/12 2009
- var defaultEvalTimeHi = -1; // current time
- var defaultEvalTimeStep = 86400; // secs per day
var defaultMedianWinSize = 8;
// Variables to support highlighting of values that contribute to combination matches:
@@ -351,9 +329,6 @@ function IndexSection()
// Load non-filter values ...
document.getElementById("ixBaseTime").value = reply.baseTimestamp;
- document.getElementById("ixEvalLoTime").value = reply.evalLoTime;
- document.getElementById("ixEvalHiTime").value = reply.evalHiTime;
- document.getElementById("ixEvalStep").value = reply.evalStep;
document.getElementById("ixMedianWinSize").value = reply.medianWinSize;
// Load filter values ...
@@ -505,10 +480,6 @@ function IndexSection()
var args = [
"index", "put", "config", "-name", "'" + configName + "'",
"-basetimestamp", document.getElementById("ixBaseTime").value,
- "-evaltimerange",
- document.getElementById("ixEvalLoTime").value,
- document.getElementById("ixEvalHiTime").value,
- document.getElementById("ixEvalStep").value,
"-medianwinsize", document.getElementById("ixMedianWinSize").value
];
@@ -557,9 +528,6 @@ function IndexSection()
"onmouseover",
"updateEvalLink("
+ defaultBaseTime
- + ", " + defaultEvalTimeLo
- + ", " + defaultEvalTimeHi
- + ", " + defaultEvalTimeStep
+ ", " + defaultMedianWinSize
+ ")"
);
@@ -615,36 +583,6 @@ function IndexSection()
input.setAttribute("id", "ixBaseTime");
input.setAttribute("value", defaultBaseTime);
- // ... low evaluation timestamp ...
- tr = table.insertRow(table.rows.length);
- td = tr.insertCell(0);
- td.innerHTML = "Low evaluation timestamp (secs since 1970): ";
- td = tr.insertCell(1);
- input = td.appendChild(document.createElement("input"));
- input.setAttribute("type", "text");
- input.setAttribute("id", "ixEvalLoTime");
- input.setAttribute("value", defaultEvalTimeLo);
-
- // ... high evaluation timestamp ...
- tr = table.insertRow(table.rows.length);
- td = tr.insertCell(0);
- td.innerHTML = "High evaluation timestamp (secs since 1970): ";
- td = tr.insertCell(1);
- input = td.appendChild(document.createElement("input"));
- input.setAttribute("type", "text");
- input.setAttribute("id", "ixEvalHiTime");
- input.setAttribute("value", defaultEvalTimeHi);
-
- // ... evaluation time step ...
- tr = table.insertRow(table.rows.length);
- td = tr.insertCell(0);
- td.innerHTML = "Evaluation time step (secs): ";
- td = tr.insertCell(1);
- input = td.appendChild(document.createElement("input"));
- input.setAttribute("type", "text");
- input.setAttribute("id", "ixEvalStep");
- input.setAttribute("value", defaultEvalTimeStep);
-
// ... median window size ...
tr = table.insertRow(table.rows.length);
td = tr.insertCell(0);