summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--metrics/src/tests/valuemetrictest.cpp8
-rw-r--r--metrics/src/vespa/metrics/valuemetric.h25
-rw-r--r--metrics/src/vespa/metrics/valuemetric.hpp6
-rw-r--r--searchcore/src/tests/proton/matching/matching_stats_test.cpp101
-rw-r--r--searchcore/src/vespa/searchcore/proton/matching/matching_stats.h38
-rw-r--r--searchcore/src/vespa/searchcore/proton/metrics/legacy_documentdb_metrics.cpp21
6 files changed, 166 insertions, 33 deletions
diff --git a/metrics/src/tests/valuemetrictest.cpp b/metrics/src/tests/valuemetrictest.cpp
index 745edf44081..e8c144c96aa 100644
--- a/metrics/src/tests/valuemetrictest.cpp
+++ b/metrics/src/tests/valuemetrictest.cpp
@@ -187,10 +187,10 @@ void ValueMetricTest::testSmallAverage()
void ValueMetricTest::testAddValueBatch() {
DoubleValueMetric m("test", "tag", "description");
- m.addValueBatch(100, 3);
- ASSERT_AVERAGE(m, 100, 100, 100, 3, 100);
- m.addValueBatch(0, 0);
- ASSERT_AVERAGE(m, 100, 100, 100, 3, 100);
+ m.addValueBatch(100, 3, 80, 120);
+ ASSERT_AVERAGE(m, 100, 80, 120, 3, 100);
+ m.addValueBatch(123, 0, 12, 1234);
+ ASSERT_AVERAGE(m, 100, 80, 120, 3, 100);
}
namespace {
diff --git a/metrics/src/vespa/metrics/valuemetric.h b/metrics/src/vespa/metrics/valuemetric.h
index 3a9e90be721..0c40a0fa5ea 100644
--- a/metrics/src/vespa/metrics/valuemetric.h
+++ b/metrics/src/vespa/metrics/valuemetric.h
@@ -65,7 +65,10 @@ class ValueMetric : public AbstractValueMetric {
void dec(const Values &values);
- void addValueWithCount(AvgVal avg, TotVal tot, uint32_t count);
+ void addValueWithCount(AvgVal avg, TotVal tot, uint32_t count, AvgVal min, AvgVal max);
+ void addValueWithCount(AvgVal avg, TotVal tot, uint32_t count) {
+ addValueWithCount(avg, tot, count, avg, avg);
+ }
// Finite number (not infinity/NaN) check using type trait tag dispatch.
// 2nd param is instance of std::true_type iff AvgVal is floating point.
@@ -110,12 +113,20 @@ public:
ValueMetric t(a); t += b; return t;
}
- void addAvgValueWithCount(AvgVal avg, uint32_t count)
- { if (count) { addValueWithCount(avg, avg * count, count); } }
- void addTotalValueWithCount(TotVal tot, uint32_t count)
- { if (count) { addValueWithCount(tot / count, tot, count); } }
- void addValueBatch(AvgVal avg, uint32_t count) {
- addAvgValueWithCount(avg, count);
+ void addAvgValueWithCount(AvgVal avg, uint32_t count) {
+ if (count > 0) {
+ addValueWithCount(avg, avg * count, count);
+ }
+ }
+ void addTotalValueWithCount(TotVal tot, uint32_t count) {
+ if (count > 0) {
+ addValueWithCount(tot / count, tot, count);
+ }
+ }
+ void addValueBatch(AvgVal avg, uint32_t count, AvgVal min, AvgVal max) {
+ if (count > 0) {
+ addValueWithCount(avg, avg * count, count, min, max);
+ }
}
virtual void addValue(AvgVal avg) { addAvgValueWithCount(avg, 1); }
virtual void set(AvgVal avg) { addValue(avg); }
diff --git a/metrics/src/vespa/metrics/valuemetric.hpp b/metrics/src/vespa/metrics/valuemetric.hpp
index 18c7837efb8..f8b4d1626ab 100644
--- a/metrics/src/vespa/metrics/valuemetric.hpp
+++ b/metrics/src/vespa/metrics/valuemetric.hpp
@@ -157,7 +157,7 @@ ValueMetric<AvgVal, TotVal, SumOnAdd>::dec(const Values& values2)
template<typename AvgVal, typename TotVal, bool SumOnAdd>
void ValueMetric<AvgVal, TotVal, SumOnAdd>::addValueWithCount(
- AvgVal avg, TotVal tot, uint32_t count)
+ AvgVal avg, TotVal tot, uint32_t count, AvgVal min, AvgVal max)
{
if (!checkFinite(avg, std::is_floating_point<AvgVal>())) {
return;
@@ -167,8 +167,8 @@ void ValueMetric<AvgVal, TotVal, SumOnAdd>::addValueWithCount(
values = _values.getValues();
values._count += count;
values._total += tot;
- if (avg < values._min) values._min = avg;
- if (avg > values._max) values._max = avg;
+ if (min < values._min) values._min = min;
+ if (max > values._max) values._max = max;
values._last = avg;
} while (!_values.setValues(values));
}
diff --git a/searchcore/src/tests/proton/matching/matching_stats_test.cpp b/searchcore/src/tests/proton/matching/matching_stats_test.cpp
index cc256e0c729..8b58a9e271c 100644
--- a/searchcore/src/tests/proton/matching/matching_stats_test.cpp
+++ b/searchcore/src/tests/proton/matching/matching_stats_test.cpp
@@ -88,6 +88,62 @@ TEST("requireThatAverageTimesAreRecorded") {
EXPECT_EQUAL(4u, stats.queryLatencyCount());
}
+TEST("requireThatMinMaxTimesAreRecorded") {
+ MatchingStats stats;
+ EXPECT_APPROX(0.0, stats.matchTimeMin(), 0.00001);
+ EXPECT_APPROX(0.0, stats.groupingTimeMin(), 0.00001);
+ EXPECT_APPROX(0.0, stats.rerankTimeMin(), 0.00001);
+ EXPECT_APPROX(0.0, stats.queryCollateralTimeMin(), 0.00001);
+ EXPECT_APPROX(0.0, stats.queryLatencyMin(), 0.00001);
+ EXPECT_APPROX(0.0, stats.matchTimeMax(), 0.00001);
+ EXPECT_APPROX(0.0, stats.groupingTimeMax(), 0.00001);
+ EXPECT_APPROX(0.0, stats.rerankTimeMax(), 0.00001);
+ EXPECT_APPROX(0.0, stats.queryCollateralTimeMax(), 0.00001);
+ EXPECT_APPROX(0.0, stats.queryLatencyMax(), 0.00001);
+ stats.matchTime(0.01).groupingTime(0.1).rerankTime(0.5).queryCollateralTime(2.0).queryLatency(1.0);
+ EXPECT_APPROX(0.01, stats.matchTimeMin(), 0.00001);
+ EXPECT_APPROX(0.1, stats.groupingTimeMin(), 0.00001);
+ EXPECT_APPROX(0.5, stats.rerankTimeMin(), 0.00001);
+ EXPECT_APPROX(2.0, stats.queryCollateralTimeMin(), 0.00001);
+ EXPECT_APPROX(1.0, stats.queryLatencyMin(), 0.00001);
+ EXPECT_APPROX(0.01, stats.matchTimeMax(), 0.00001);
+ EXPECT_APPROX(0.1, stats.groupingTimeMax(), 0.00001);
+ EXPECT_APPROX(0.5, stats.rerankTimeMax(), 0.00001);
+ EXPECT_APPROX(2.0, stats.queryCollateralTimeMax(), 0.00001);
+ EXPECT_APPROX(1.0, stats.queryLatencyMax(), 0.00001);
+ stats.add(MatchingStats().matchTime(0.03).groupingTime(0.3).rerankTime(1.5).queryCollateralTime(6.0).queryLatency(3.0));
+ EXPECT_APPROX(0.01, stats.matchTimeMin(), 0.00001);
+ EXPECT_APPROX(0.1, stats.groupingTimeMin(), 0.00001);
+ EXPECT_APPROX(0.5, stats.rerankTimeMin(), 0.00001);
+ EXPECT_APPROX(2.0, stats.queryCollateralTimeMin(), 0.00001);
+ EXPECT_APPROX(1.0, stats.queryLatencyMin(), 0.00001);
+ EXPECT_APPROX(0.03, stats.matchTimeMax(), 0.00001);
+ EXPECT_APPROX(0.3, stats.groupingTimeMax(), 0.00001);
+ EXPECT_APPROX(1.5, stats.rerankTimeMax(), 0.00001);
+ EXPECT_APPROX(6.0, stats.queryCollateralTimeMax(), 0.00001);
+ EXPECT_APPROX(3.0, stats.queryLatencyMax(), 0.00001);
+ stats.add(MatchingStats().matchTime(0.05)
+ .groupingTime(0.5)
+ .rerankTime(2.5)
+ .queryCollateralTime(10.0)
+ .queryLatency(5.0));
+ stats.add(MatchingStats().matchTime(0.05).matchTime(0.03)
+ .groupingTime(0.5).groupingTime(0.3)
+ .rerankTime(2.5).rerankTime(1.5)
+ .queryCollateralTime(10.0).queryCollateralTime(6.0)
+ .queryLatency(5.0).queryLatency(3.0));
+ EXPECT_APPROX(0.01, stats.matchTimeMin(), 0.00001);
+ EXPECT_APPROX(0.1, stats.groupingTimeMin(), 0.00001);
+ EXPECT_APPROX(0.5, stats.rerankTimeMin(), 0.00001);
+ EXPECT_APPROX(2.0, stats.queryCollateralTimeMin(), 0.00001);
+ EXPECT_APPROX(1.0, stats.queryLatencyMin(), 0.00001);
+ EXPECT_APPROX(0.05, stats.matchTimeMax(), 0.00001);
+ EXPECT_APPROX(0.5, stats.groupingTimeMax(), 0.00001);
+ EXPECT_APPROX(2.5, stats.rerankTimeMax(), 0.00001);
+ EXPECT_APPROX(10.0, stats.queryCollateralTimeMax(), 0.00001);
+ EXPECT_APPROX(5.0, stats.queryLatencyMax(), 0.00001);
+}
+
TEST("requireThatPartitionsAreAddedCorrectly") {
MatchingStats all1;
EXPECT_EQUAL(0u, all1.docidSpaceCovered());
@@ -105,6 +161,10 @@ TEST("requireThatPartitionsAreAddedCorrectly") {
EXPECT_EQUAL(0.5, subPart.wait_time_avg());
EXPECT_EQUAL(1u, subPart.active_time_count());
EXPECT_EQUAL(1u, subPart.wait_time_count());
+ EXPECT_EQUAL(1.0, subPart.active_time_min());
+ EXPECT_EQUAL(0.5, subPart.wait_time_min());
+ EXPECT_EQUAL(1.0, subPart.active_time_max());
+ EXPECT_EQUAL(0.5, subPart.wait_time_max());
all1.merge_partition(subPart, 0);
EXPECT_EQUAL(7u, all1.docidSpaceCovered());
@@ -120,8 +180,15 @@ TEST("requireThatPartitionsAreAddedCorrectly") {
EXPECT_EQUAL(0.5, all1.getPartition(0).wait_time_avg());
EXPECT_EQUAL(1u, all1.getPartition(0).active_time_count());
EXPECT_EQUAL(1u, all1.getPartition(0).wait_time_count());
-
- all1.merge_partition(subPart, 1);
+ EXPECT_EQUAL(1.0, all1.getPartition(0).active_time_min());
+ EXPECT_EQUAL(0.5, all1.getPartition(0).wait_time_min());
+ EXPECT_EQUAL(1.0, all1.getPartition(0).active_time_max());
+ EXPECT_EQUAL(0.5, all1.getPartition(0).wait_time_max());
+
+ MatchingStats::Partition otherSubPart;
+ otherSubPart.docsCovered(7).docsMatched(3).docsRanked(2).docsReRanked(1)
+ .active_time(0.5).wait_time(1.0);
+ all1.merge_partition(otherSubPart, 1);
EXPECT_EQUAL(14u, all1.docidSpaceCovered());
EXPECT_EQUAL(6u, all1.docsMatched());
EXPECT_EQUAL(4u, all1.docsRanked());
@@ -130,12 +197,20 @@ TEST("requireThatPartitionsAreAddedCorrectly") {
EXPECT_EQUAL(3u, all1.getPartition(1).docsMatched());
EXPECT_EQUAL(2u, all1.getPartition(1).docsRanked());
EXPECT_EQUAL(1u, all1.getPartition(1).docsReRanked());
- EXPECT_EQUAL(1.0, all1.getPartition(1).active_time_avg());
- EXPECT_EQUAL(0.5, all1.getPartition(1).wait_time_avg());
+ EXPECT_EQUAL(0.5, all1.getPartition(1).active_time_avg());
+ EXPECT_EQUAL(1.0, all1.getPartition(1).wait_time_avg());
EXPECT_EQUAL(1u, all1.getPartition(1).active_time_count());
EXPECT_EQUAL(1u, all1.getPartition(1).wait_time_count());
+ EXPECT_EQUAL(0.5, all1.getPartition(1).active_time_min());
+ EXPECT_EQUAL(1.0, all1.getPartition(1).wait_time_min());
+ EXPECT_EQUAL(0.5, all1.getPartition(1).active_time_max());
+ EXPECT_EQUAL(1.0, all1.getPartition(1).wait_time_max());
+
+ MatchingStats all2;
+ all2.merge_partition(otherSubPart, 0);
+ all2.merge_partition(subPart, 1);
- all1.add(all1);
+ all1.add(all2);
EXPECT_EQUAL(28u, all1.docidSpaceCovered());
EXPECT_EQUAL(12u, all1.docsMatched());
EXPECT_EQUAL(8u, all1.docsRanked());
@@ -144,17 +219,25 @@ TEST("requireThatPartitionsAreAddedCorrectly") {
EXPECT_EQUAL(6u, all1.getPartition(0).docsMatched());
EXPECT_EQUAL(4u, all1.getPartition(0).docsRanked());
EXPECT_EQUAL(2u, all1.getPartition(0).docsReRanked());
- EXPECT_EQUAL(1.0, all1.getPartition(0).active_time_avg());
- EXPECT_EQUAL(0.5, all1.getPartition(0).wait_time_avg());
+ EXPECT_EQUAL(0.75, all1.getPartition(0).active_time_avg());
+ EXPECT_EQUAL(0.75, all1.getPartition(0).wait_time_avg());
EXPECT_EQUAL(2u, all1.getPartition(0).active_time_count());
EXPECT_EQUAL(2u, all1.getPartition(0).wait_time_count());
+ EXPECT_EQUAL(0.5, all1.getPartition(0).active_time_min());
+ EXPECT_EQUAL(0.5, all1.getPartition(0).wait_time_min());
+ EXPECT_EQUAL(1.0, all1.getPartition(0).active_time_max());
+ EXPECT_EQUAL(1.0, all1.getPartition(0).wait_time_max());
EXPECT_EQUAL(6u, all1.getPartition(1).docsMatched());
EXPECT_EQUAL(4u, all1.getPartition(1).docsRanked());
EXPECT_EQUAL(2u, all1.getPartition(1).docsReRanked());
- EXPECT_EQUAL(1.0, all1.getPartition(1).active_time_avg());
- EXPECT_EQUAL(0.5, all1.getPartition(1).wait_time_avg());
+ EXPECT_EQUAL(0.75, all1.getPartition(1).active_time_avg());
+ EXPECT_EQUAL(0.75, all1.getPartition(1).wait_time_avg());
EXPECT_EQUAL(2u, all1.getPartition(1).active_time_count());
EXPECT_EQUAL(2u, all1.getPartition(1).wait_time_count());
+ EXPECT_EQUAL(0.5, all1.getPartition(1).active_time_min());
+ EXPECT_EQUAL(0.5, all1.getPartition(1).wait_time_min());
+ EXPECT_EQUAL(1.0, all1.getPartition(1).active_time_max());
+ EXPECT_EQUAL(1.0, all1.getPartition(1).wait_time_max());
}
TEST_MAIN() {
diff --git a/searchcore/src/vespa/searchcore/proton/matching/matching_stats.h b/searchcore/src/vespa/searchcore/proton/matching/matching_stats.h
index 6df01afaa4d..b58468fe1bc 100644
--- a/searchcore/src/vespa/searchcore/proton/matching/matching_stats.h
+++ b/searchcore/src/vespa/searchcore/proton/matching/matching_stats.h
@@ -19,12 +19,30 @@ private:
class Avg {
double _value;
size_t _count;
+ double _min;
+ double _max;
public:
- Avg() : _value(0.0), _count(0) {}
- void set(double value) { _value = value; _count = 1; }
- double avg() const { return !_count ? 0 : _value / _count; }
+ Avg() : _value(0.0), _count(0), _min(0.0), _max(0.0) {}
+ void set(double value) {
+ _value = value;
+ _count = 1;
+ _min = value;
+ _max = value;
+ }
+ double avg() const {
+ return (_count > 0) ? (_value / _count) : 0;
+ }
size_t count() const { return _count; }
+ double min() const { return _min; }
+ double max() const { return _max; }
void add(const Avg &other) {
+ if (_count == 0) {
+ _min = other._min;
+ _max = other._max;
+ } else if (other._count > 0) {
+ _min = std::min(_min, other._min);
+ _max = std::max(_max, other._max);
+ }
_value += other._value;
_count += other._count;
}
@@ -68,9 +86,13 @@ public:
Partition &active_time(double time_s) { _active_time.set(time_s); return *this; }
double active_time_avg() const { return _active_time.avg(); }
size_t active_time_count() const { return _active_time.count(); }
+ double active_time_min() const { return _active_time.min(); }
+ double active_time_max() const { return _active_time.max(); }
Partition &wait_time(double time_s) { _wait_time.set(time_s); return *this; }
double wait_time_avg() const { return _wait_time.avg(); }
size_t wait_time_count() const { return _wait_time.count(); }
+ double wait_time_min() const { return _wait_time.min(); }
+ double wait_time_max() const { return _wait_time.max(); }
Partition &add(const Partition &rhs) {
_docsCovered += rhs.docsCovered();
@@ -136,22 +158,32 @@ public:
MatchingStats &queryCollateralTime(double time_s) { _queryCollateralTime.set(time_s); return *this; }
double queryCollateralTimeAvg() const { return _queryCollateralTime.avg(); }
size_t queryCollateralTimeCount() const { return _queryCollateralTime.count(); }
+ double queryCollateralTimeMin() const { return _queryCollateralTime.min(); }
+ double queryCollateralTimeMax() const { return _queryCollateralTime.max(); }
MatchingStats &queryLatency(double time_s) { _queryLatency.set(time_s); return *this; }
double queryLatencyAvg() const { return _queryLatency.avg(); }
size_t queryLatencyCount() const { return _queryLatency.count(); }
+ double queryLatencyMin() const { return _queryLatency.min(); }
+ double queryLatencyMax() const { return _queryLatency.max(); }
MatchingStats &matchTime(double time_s) { _matchTime.set(time_s); return *this; }
double matchTimeAvg() const { return _matchTime.avg(); }
size_t matchTimeCount() const { return _matchTime.count(); }
+ double matchTimeMin() const { return _matchTime.min(); }
+ double matchTimeMax() const { return _matchTime.max(); }
MatchingStats &groupingTime(double time_s) { _groupingTime.set(time_s); return *this; }
double groupingTimeAvg() const { return _groupingTime.avg(); }
size_t groupingTimeCount() const { return _groupingTime.count(); }
+ double groupingTimeMin() const { return _groupingTime.min(); }
+ double groupingTimeMax() const { return _groupingTime.max(); }
MatchingStats &rerankTime(double time_s) { _rerankTime.set(time_s); return *this; }
double rerankTimeAvg() const { return _rerankTime.avg(); }
size_t rerankTimeCount() const { return _rerankTime.count(); }
+ double rerankTimeMin() const { return _rerankTime.min(); }
+ double rerankTimeMax() const { return _rerankTime.max(); }
// used to merge in stats from each match thread
MatchingStats &merge_partition(const Partition &partition, size_t id);
diff --git a/searchcore/src/vespa/searchcore/proton/metrics/legacy_documentdb_metrics.cpp b/searchcore/src/vespa/searchcore/proton/metrics/legacy_documentdb_metrics.cpp
index 2c753d24c69..4d23c3f1603 100644
--- a/searchcore/src/vespa/searchcore/proton/metrics/legacy_documentdb_metrics.cpp
+++ b/searchcore/src/vespa/searchcore/proton/metrics/legacy_documentdb_metrics.cpp
@@ -41,8 +41,10 @@ LegacyDocumentDBMetrics::MatchingMetrics::update(const MatchingStats &stats)
docsReRanked.inc(stats.docsReRanked());
softDoomFactor.set(stats.softDoomFactor());
queries.inc(stats.queries());
- queryCollateralTime.addValueBatch(stats.queryCollateralTimeAvg(), stats.queryCollateralTimeCount());
- queryLatency.addValueBatch(stats.queryLatencyAvg(), stats.queryLatencyCount());
+ queryCollateralTime.addValueBatch(stats.queryCollateralTimeAvg(), stats.queryCollateralTimeCount(),
+ stats.queryCollateralTimeMin(), stats.queryCollateralTimeMax());
+ queryLatency.addValueBatch(stats.queryLatencyAvg(), stats.queryLatencyCount(),
+ stats.queryLatencyMin(), stats.queryLatencyMax());
}
LegacyDocumentDBMetrics::MatchingMetrics::MatchingMetrics(MetricSet *parent)
@@ -92,8 +94,10 @@ LegacyDocumentDBMetrics::MatchingMetrics::RankProfileMetrics::DocIdPartition::up
docsMatched.inc(stats.docsMatched());
docsRanked.inc(stats.docsRanked());
docsReRanked.inc(stats.docsReRanked());
- active_time.addValueBatch(stats.active_time_avg(), stats.active_time_count());
- wait_time.addValueBatch(stats.wait_time_avg(), stats.wait_time_count());
+ active_time.addValueBatch(stats.active_time_avg(), stats.active_time_count(),
+ stats.active_time_min(), stats.active_time_max());
+ wait_time.addValueBatch(stats.wait_time_avg(), stats.wait_time_count(),
+ stats.wait_time_min(), stats.wait_time_max());
}
void
@@ -101,9 +105,12 @@ LegacyDocumentDBMetrics::MatchingMetrics::RankProfileMetrics::update(const Match
{
queries.inc(stats.queries());
limited_queries.inc(stats.limited_queries());
- matchTime.addValueBatch(stats.matchTimeAvg(), stats.matchTimeCount());
- groupingTime.addValueBatch(stats.groupingTimeAvg(), stats.groupingTimeCount());
- rerankTime.addValueBatch(stats.rerankTimeAvg(), stats.rerankTimeCount());
+ matchTime.addValueBatch(stats.matchTimeAvg(), stats.matchTimeCount(),
+ stats.matchTimeMin(), stats.matchTimeMax());
+ groupingTime.addValueBatch(stats.groupingTimeAvg(), stats.groupingTimeCount(),
+ stats.groupingTimeMin(), stats.groupingTimeMax());
+ rerankTime.addValueBatch(stats.rerankTimeAvg(), stats.rerankTimeCount(),
+ stats.rerankTimeMin(), stats.rerankTimeMax());
if (stats.getNumPartitions() > 0) {
if (stats.getNumPartitions() <= partitions.size()) {
for (size_t i(0), m(stats.getNumPartitions()); i < m; i++) {