diff options
14 files changed, 249 insertions, 52 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java index 48c85aed640..36221d978a1 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/Node.java @@ -732,6 +732,7 @@ public final class Node implements Nodelike { private final State state; private final NodeType type; + private String extraId; private String parentHostname; private String modelName; private TenantName reservedTo; @@ -758,6 +759,11 @@ public final class Node implements Nodelike { this.type = type; } + public Builder extraId(String extraId) { + this.extraId = extraId; + return this; + } + public Builder parentHostname(String parentHostname) { this.parentHostname = parentHostname; return this; @@ -849,7 +855,7 @@ public final class Node implements Nodelike { } public Node build() { - return new Node(id, Optional.empty(), Optional.ofNullable(ipConfig).orElse(IP.Config.EMPTY), hostname, Optional.ofNullable(parentHostname), + return new Node(id, Optional.ofNullable(extraId), Optional.ofNullable(ipConfig).orElse(IP.Config.EMPTY), hostname, Optional.ofNullable(parentHostname), flavor, Optional.ofNullable(status).orElseGet(Status::initial), state, Optional.ofNullable(allocation), Optional.ofNullable(history).orElseGet(History::empty), type, Optional.ofNullable(reports).orElseGet(Reports::new), Optional.ofNullable(modelName), Optional.ofNullable(reservedTo), Optional.ofNullable(exclusiveToApplicationId), diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesV2ApiHandler.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesV2ApiHandler.java index 0b157e8635b..cef28045a8b 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesV2ApiHandler.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/NodesV2ApiHandler.java @@ -302,6 +302,7 @@ public class NodesV2ApiHandler extends ThreadedHttpRequestHandler { flavorFromSlime(inspector), nodeTypeFromSlime(inspector.field("type"))) .cloudAccount(nodeRepository.zone().cloud().account()); + optionalString(inspector.field("extraId")).ifPresent(builder::extraId); optionalString(inspector.field("parentHostname")).ifPresent(builder::parentHostname); optionalString(inspector.field("modelName")).ifPresent(builder::modelName); optionalString(inspector.field("reservedTo")).map(TenantName::from).ifPresent(builder::reservedTo); diff --git a/searchlib/src/tests/queryeval/blueprint/intermediate_blueprints_test.cpp b/searchlib/src/tests/queryeval/blueprint/intermediate_blueprints_test.cpp index ee7c201f093..31db731a598 100644 --- a/searchlib/src/tests/queryeval/blueprint/intermediate_blueprints_test.cpp +++ b/searchlib/src/tests/queryeval/blueprint/intermediate_blueprints_test.cpp @@ -165,20 +165,30 @@ TEST("test Or propagates updated histestimate") { bp->addChild(ap(MyLeafSpec(800).create<RememberExecuteInfo>()->setSourceId(2))); bp->addChild(ap(MyLeafSpec(20).create<RememberExecuteInfo>()->setSourceId(2))); bp->setDocIdLimit(5000); - // sort OR as non-strict to get expected order. With strict OR, - // the order would be irrelevant since we use the relative - // estimate as strict_cost for leafs. + // NOTE: use non-strict OR ordering since strict OR ordering is non-deterministic optimize(bp, false); - bp->fetchPostings(ExecuteInfo::TRUE); + //--- execute info when non-strict: + bp->fetchPostings(ExecuteInfo::FALSE); EXPECT_EQUAL(4u, bp->childCnt()); for (uint32_t i = 0; i < bp->childCnt(); i++) { const auto & child = dynamic_cast<const RememberExecuteInfo &>(bp->getChild(i)); - EXPECT_TRUE(child.is_strict); + EXPECT_FALSE(child.is_strict); } EXPECT_EQUAL(1.0, dynamic_cast<const RememberExecuteInfo &>(bp->getChild(0)).hit_rate); EXPECT_APPROX(0.5, dynamic_cast<const RememberExecuteInfo &>(bp->getChild(1)).hit_rate, 1e-6); EXPECT_APPROX(0.5*3.0/5.0, dynamic_cast<const RememberExecuteInfo &>(bp->getChild(2)).hit_rate, 1e-6); EXPECT_APPROX(0.5*3.0*42.0/(5.0*50.0), dynamic_cast<const RememberExecuteInfo &>(bp->getChild(3)).hit_rate, 1e-6); + //--- execute info when strict: + bp->fetchPostings(ExecuteInfo::TRUE); + EXPECT_EQUAL(4u, bp->childCnt()); + for (uint32_t i = 0; i < bp->childCnt(); i++) { + const auto & child = dynamic_cast<const RememberExecuteInfo &>(bp->getChild(i)); + EXPECT_TRUE(child.is_strict); + } + EXPECT_EQUAL(1.0, dynamic_cast<const RememberExecuteInfo &>(bp->getChild(0)).hit_rate); + EXPECT_EQUAL(1.0, dynamic_cast<const RememberExecuteInfo &>(bp->getChild(1)).hit_rate); + EXPECT_EQUAL(1.0, dynamic_cast<const RememberExecuteInfo &>(bp->getChild(2)).hit_rate); + EXPECT_EQUAL(1.0, dynamic_cast<const RememberExecuteInfo &>(bp->getChild(3)).hit_rate); } TEST("test And Blueprint") { diff --git a/searchlib/src/tests/queryeval/flow/queryeval_flow_test.cpp b/searchlib/src/tests/queryeval/flow/queryeval_flow_test.cpp index 7a3950dbf1c..5009a15e438 100644 --- a/searchlib/src/tests/queryeval/flow/queryeval_flow_test.cpp +++ b/searchlib/src/tests/queryeval/flow/queryeval_flow_test.cpp @@ -126,6 +126,14 @@ void verify_flow(auto flow, const std::vector<double> &est_list, const std::vect } } +void verify_flow_calc(FlowCalc flow_calc, const std::vector<double> &est_list, const std::vector<double> &expect) { + ASSERT_EQ(est_list.size() + 1, expect.size()); + for (size_t i = 0; i < est_list.size(); ++i) { + EXPECT_DOUBLE_EQ(flow_calc(est_list[i]), expect[i]); + } + EXPECT_DOUBLE_EQ(flow_calc(0.5), expect.back()); +} + TEST(FlowTest, full_and_flow) { for (bool strict: {false, true}) { verify_flow(AndFlow(strict), {0.4, 0.7, 0.2}, @@ -133,6 +141,8 @@ TEST(FlowTest, full_and_flow) { {0.4, 0.4, false}, {0.4*0.7, 0.4*0.7, false}, {0.4*0.7*0.2, 0.4*0.7*0.2, false}}); + verify_flow_calc(flow_calc<AndFlow>(strict, 1.0), + {0.4, 0.7, 0.2}, {1.0, 0.4, 0.4*0.7, 0.4*0.7*0.2}); } } @@ -143,6 +153,8 @@ TEST(FlowTest, partial_and_flow) { {in*0.4, in*0.4, false}, {in*0.4*0.7, in*0.4*0.7, false}, {in*0.4*0.7*0.2, in*0.4*0.7*0.2, false}}); + verify_flow_calc(flow_calc<AndFlow>(false, in), + {0.4, 0.7, 0.2}, {in*1.0, in*0.4, in*0.4*0.7, in*0.4*0.7*0.2}); } } @@ -152,11 +164,15 @@ TEST(FlowTest, full_or_flow) { {0.6, 1.0-0.6, false}, {0.6*0.3, 1.0-0.6*0.3, false}, {0.6*0.3*0.8, 1.0-0.6*0.3*0.8, false}}); + verify_flow_calc(flow_calc<OrFlow>(false, 1.0), + {0.4, 0.7, 0.2}, {1.0, 0.6, 0.6*0.3, 0.6*0.3*0.8}); verify_flow(OrFlow(true), {0.4, 0.7, 0.2}, {{1.0, 0.0, true}, {1.0, 1.0-0.6, true}, {1.0, 1.0-0.6*0.3, true}, {1.0, 1.0-0.6*0.3*0.8, true}}); + verify_flow_calc(flow_calc<OrFlow>(true, 1.0), + {0.4, 0.7, 0.2}, {1.0, 1.0, 1.0, 1.0}); } TEST(FlowTest, partial_or_flow) { @@ -166,6 +182,8 @@ TEST(FlowTest, partial_or_flow) { {in*0.6, 1.0-in*0.6, false}, {in*0.6*0.3, 1.0-in*0.6*0.3, false}, {in*0.6*0.3*0.8, 1.0-in*0.6*0.3*0.8, false}}); + verify_flow_calc(flow_calc<OrFlow>(false, in), + {0.4, 0.7, 0.2}, {in, in*0.6, in*0.6*0.3, in*0.6*0.3*0.8}); } } @@ -176,6 +194,8 @@ TEST(FlowTest, full_and_not_flow) { {0.4, 0.4, false}, {0.4*0.3, 0.4*0.3, false}, {0.4*0.3*0.8, 0.4*0.3*0.8, false}}); + verify_flow_calc(flow_calc<AndNotFlow>(strict, 1.0), + {0.4, 0.7, 0.2}, {1.0, 0.4, 0.4*0.3, 0.4*0.3*0.8}); } } @@ -186,9 +206,47 @@ TEST(FlowTest, partial_and_not_flow) { {in*0.4, in*0.4, false}, {in*0.4*0.3, in*0.4*0.3, false}, {in*0.4*0.3*0.8, in*0.4*0.3*0.8, false}}); + verify_flow_calc(flow_calc<AndNotFlow>(false, in), + {0.4, 0.7, 0.2}, {in, in*0.4, in*0.4*0.3, in*0.4*0.3*0.8}); + } +} + +TEST(FlowTest, full_first_flow_calc) { + for (bool strict: {false, true}) { + verify_flow_calc(first_flow_calc(strict, 1.0), + {0.4, 0.7, 0.2}, {1.0, 0.4, 0.4, 0.4}); + } +} + +TEST(FlowTest, partial_first_flow_calc) { + for (double in: {1.0, 0.5, 0.25}) { + verify_flow_calc(first_flow_calc(false, in), + {0.4, 0.7, 0.2}, {in, in*0.4, in*0.4, in*0.4}); + } +} + +TEST(FlowTest, full_full_flow_calc) { + for (bool strict: {false, true}) { + verify_flow_calc(full_flow_calc(strict, 1.0), + {0.4, 0.7, 0.2}, {1.0, 1.0, 1.0, 1.0}); } } +TEST(FlowTest, partial_full_flow_calc) { + for (double in: {1.0, 0.5, 0.25}) { + verify_flow_calc(full_flow_calc(false, in), + {0.4, 0.7, 0.2}, {in, in, in, in}); + } +} + +TEST(FlowTest, flow_calc_strictness_overrides_rate) { + EXPECT_EQ(flow_calc<AndFlow>(true, 0.5)(0.5), 1.0); + EXPECT_EQ(flow_calc<OrFlow>(true, 0.5)(0.5), 1.0); + EXPECT_EQ(flow_calc<AndNotFlow>(true, 0.5)(0.5), 1.0); + EXPECT_EQ(first_flow_calc(true, 0.5)(0.5), 1.0); + EXPECT_EQ(full_flow_calc(true, 0.5)(0.5), 1.0); +} + TEST(FlowTest, flow_cost) { std::vector<FlowStats> data = {{0.4, 1.1, 0.6}, {0.7, 1.2, 0.5}, {0.2, 1.3, 0.4}}; EXPECT_DOUBLE_EQ(ordered_cost_of<AndFlow>(data, false), 1.1 + 0.4*1.2 + 0.4*0.7*1.3); diff --git a/searchlib/src/vespa/searchlib/attribute/CMakeLists.txt b/searchlib/src/vespa/searchlib/attribute/CMakeLists.txt index 96bd07bc5a3..4f886cf2dd4 100644 --- a/searchlib/src/vespa/searchlib/attribute/CMakeLists.txt +++ b/searchlib/src/vespa/searchlib/attribute/CMakeLists.txt @@ -111,6 +111,7 @@ vespa_add_library(searchlib_attribute OBJECT postinglisttraits.cpp postingstore.cpp predicate_attribute.cpp + predicate_attribute_saver.cpp raw_attribute.cpp raw_buffer_store.cpp raw_buffer_store_reader.cpp diff --git a/searchlib/src/vespa/searchlib/attribute/predicate_attribute.cpp b/searchlib/src/vespa/searchlib/attribute/predicate_attribute.cpp index 60898450e50..075616a9fe9 100644 --- a/searchlib/src/vespa/searchlib/attribute/predicate_attribute.cpp +++ b/searchlib/src/vespa/searchlib/attribute/predicate_attribute.cpp @@ -4,6 +4,7 @@ #include "attribute_header.h" #include "iattributesavetarget.h" #include "load_utils.h" +#include "predicate_attribute_saver.h" #include <vespa/document/fieldvalue/predicatefieldvalue.h> #include <vespa/document/predicate/predicate.h> #include <vespa/searchlib/predicate/i_saver.h> @@ -143,29 +144,23 @@ PredicateAttribute::before_inc_generation(generation_t current_gen) _index->assign_generation(current_gen); } -void -PredicateAttribute::onSave(IAttributeSaveTarget &saveTarget) { - LOG(info, "Saving predicate attribute version %d name '%s'", getVersion(), getName().c_str()); - IAttributeSaveTarget::Buffer buffer(saveTarget.datWriter().allocBuf(4_Ki)); - { - DataBufferWriter writer(*buffer); - auto saver = _index->make_saver(); - saver->save(writer); - writer.flush(); - } - uint32_t highest_doc_id = static_cast<uint32_t>(_min_feature.size() - 1); - buffer->writeInt32(highest_doc_id); - for (size_t i = 1; i <= highest_doc_id; ++i) { - buffer->writeInt8(_min_feature[i]); - } - for (size_t i = 1; i <= highest_doc_id; ++i) { - buffer->writeInt16(_interval_range_vector[i]); - } - buffer->writeInt16(_max_interval_range); - saveTarget.datWriter().writeBuf(std::move(buffer)); +std::unique_ptr<AttributeSaver> +PredicateAttribute::onInitSave(vespalib::stringref fileName) +{ + auto guard(getGenerationHandler().takeGuard()); + auto header = this->createAttributeHeader(fileName); + auto min_feature_view = _min_feature.make_read_view(_min_feature.size()); + auto interval_range_vector_view = _interval_range_vector.make_read_view(_interval_range_vector.size()); + return std::make_unique<PredicateAttributeSaver> + (std::move(guard), + std::move(header), + getVersion(), + _index->make_saver(), + PredicateAttributeSaver::MinFeatureVector{ min_feature_view.begin(), min_feature_view.end() }, + PredicateAttributeSaver::IntervalRangeVector{ interval_range_vector_view.begin(), interval_range_vector_view.end() }, + _max_interval_range); } - uint32_t PredicateAttribute::getVersion() const { return PREDICATE_ATTRIBUTE_VERSION; diff --git a/searchlib/src/vespa/searchlib/attribute/predicate_attribute.h b/searchlib/src/vespa/searchlib/attribute/predicate_attribute.h index acb4cbc5833..f188ac29941 100644 --- a/searchlib/src/vespa/searchlib/attribute/predicate_attribute.h +++ b/searchlib/src/vespa/searchlib/attribute/predicate_attribute.h @@ -45,7 +45,7 @@ public: predicate::PredicateIndex &getIndex() { return *_index; } - void onSave(IAttributeSaveTarget & saveTarget) override; + std::unique_ptr<AttributeSaver> onInitSave(vespalib::stringref fileName) override; bool onLoad(vespalib::Executor *executor) override; void onCommit() override; void reclaim_memory(generation_t oldest_used_gen) override; diff --git a/searchlib/src/vespa/searchlib/attribute/predicate_attribute_saver.cpp b/searchlib/src/vespa/searchlib/attribute/predicate_attribute_saver.cpp new file mode 100644 index 00000000000..aa1c3ab45a6 --- /dev/null +++ b/searchlib/src/vespa/searchlib/attribute/predicate_attribute_saver.cpp @@ -0,0 +1,52 @@ +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "predicate_attribute_saver.h" +#include "iattributesavetarget.h" +#include <vespa/searchlib/predicate/i_saver.h> +#include <vespa/searchlib/predicate/nbo_write.h> +#include <filesystem> + +#include <vespa/log/log.h> +LOG_SETUP(".searchlib.attribute.predicate_attribute_saver"); + +using search::predicate::nbo_write; + +namespace search { + +PredicateAttributeSaver::PredicateAttributeSaver(GenerationHandler::Guard &&guard, + const attribute::AttributeHeader &header, + uint32_t version, + std::unique_ptr<predicate::ISaver> index_saver, + MinFeatureVector min_feature, + IntervalRangeVector interval_range_vector, + uint16_t max_interval_range) + : AttributeSaver(std::move(guard), header), + _version(version), + _index_saver(std::move(index_saver)), + _min_feature(std::move(min_feature)), + _interval_range_vector(std::move(interval_range_vector)), + _max_interval_range(max_interval_range) +{ +} + +PredicateAttributeSaver::~PredicateAttributeSaver() = default; + +bool +PredicateAttributeSaver::onSave(IAttributeSaveTarget& save_target) +{ + auto name = std::filesystem::path(get_file_name()).filename().native(); + LOG(info, "Saving predicate attribute version %u name '%s'", _version, name.c_str()); + auto writer = save_target.datWriter().allocBufferWriter(); + _index_saver->save(*writer); + uint32_t highest_doc_id = static_cast<uint32_t>(_min_feature.size() - 1); + nbo_write<uint32_t>(*writer, highest_doc_id); + writer->write(&_min_feature[1], highest_doc_id); + for (size_t i = 1; i <= highest_doc_id; ++i) { + nbo_write<uint16_t>(*writer, _interval_range_vector[i]); + } + nbo_write<uint16_t>(*writer, _max_interval_range); + writer->flush(); + return true; +} + +} diff --git a/searchlib/src/vespa/searchlib/attribute/predicate_attribute_saver.h b/searchlib/src/vespa/searchlib/attribute/predicate_attribute_saver.h new file mode 100644 index 00000000000..28e7094091f --- /dev/null +++ b/searchlib/src/vespa/searchlib/attribute/predicate_attribute_saver.h @@ -0,0 +1,40 @@ +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include "attributesaver.h" +#include <vespa/vespalib/stllike/allocator.h> + +namespace search::predicate { class ISaver; } + +namespace search { + +/** + * Class for saving a predicate attribute. + */ +class PredicateAttributeSaver : public AttributeSaver +{ +public: + using GenerationHandler = vespalib::GenerationHandler; + using MinFeatureVector = std::vector<uint8_t, vespalib::allocator_large<uint8_t>>; + using IntervalRangeVector = std::vector<uint16_t, vespalib::allocator_large<uint16_t>>; + +private: + uint32_t _version; + std::unique_ptr<predicate::ISaver> _index_saver; + MinFeatureVector _min_feature; + IntervalRangeVector _interval_range_vector; + uint16_t _max_interval_range; +public: + PredicateAttributeSaver(GenerationHandler::Guard&& guard, + const attribute::AttributeHeader& header, + uint32_t version, + std::unique_ptr<predicate::ISaver> index_saver, + MinFeatureVector min_feature, + IntervalRangeVector interval_range_vector, + uint16_t max_interval_range); + ~PredicateAttributeSaver() override; + bool onSave(IAttributeSaveTarget& save_target) override; +}; + +} diff --git a/searchlib/src/vespa/searchlib/queryeval/blueprint.cpp b/searchlib/src/vespa/searchlib/queryeval/blueprint.cpp index 2f69c45d418..f3539c6989a 100644 --- a/searchlib/src/vespa/searchlib/queryeval/blueprint.cpp +++ b/searchlib/src/vespa/searchlib/queryeval/blueprint.cpp @@ -481,6 +481,12 @@ IntermediateBlueprint::count_termwise_nodes(const UnpackInfo &unpack) const return termwise_nodes; } +FlowCalc +IntermediateBlueprint::make_flow_calc(bool strict, double flow) const +{ + return full_flow_calc(strict, flow); +} + IntermediateBlueprint::IndexList IntermediateBlueprint::find(const IPredicate & pred) const { @@ -538,13 +544,6 @@ IntermediateBlueprint::calculateState() const return state; } -double -IntermediateBlueprint::computeNextHitRate(const Blueprint & child, double hit_rate) const -{ - (void) child; - return hit_rate; -} - bool IntermediateBlueprint::should_do_termwise_eval(const UnpackInfo &unpack, double match_limit) const { @@ -648,11 +647,11 @@ IntermediateBlueprint::visitMembers(vespalib::ObjectVisitor &visitor) const void IntermediateBlueprint::fetchPostings(const ExecuteInfo &execInfo) { - double nextHitRate = execInfo.hit_rate(); + FlowCalc flow_calc = make_flow_calc(execInfo.is_strict(), execInfo.hit_rate()); for (size_t i = 0; i < _children.size(); ++i) { Blueprint & child = *_children[i]; + double nextHitRate = flow_calc(child.estimate()); child.fetchPostings(ExecuteInfo::create(execInfo.is_strict() && inheritStrict(i), nextHitRate, execInfo)); - nextHitRate = computeNextHitRate(child, nextHitRate); } } diff --git a/searchlib/src/vespa/searchlib/queryeval/blueprint.h b/searchlib/src/vespa/searchlib/queryeval/blueprint.h index 439eff680ec..395512d84cc 100644 --- a/searchlib/src/vespa/searchlib/queryeval/blueprint.h +++ b/searchlib/src/vespa/searchlib/queryeval/blueprint.h @@ -362,7 +362,7 @@ private: bool infer_want_global_filter() const; size_t count_termwise_nodes(const UnpackInfo &unpack) const; - virtual double computeNextHitRate(const Blueprint & child, double hit_rate) const; + virtual FlowCalc make_flow_calc(bool strict, double flow) const; protected: // returns an empty collection if children have empty or diff --git a/searchlib/src/vespa/searchlib/queryeval/flow.h b/searchlib/src/vespa/searchlib/queryeval/flow.h index cfbb28b190f..4548baf7545 100644 --- a/searchlib/src/vespa/searchlib/queryeval/flow.h +++ b/searchlib/src/vespa/searchlib/queryeval/flow.h @@ -4,7 +4,7 @@ #include <vespa/vespalib/util/small_vector.h> #include <cstddef> #include <algorithm> -#include <cmath> +#include <functional> // Model how boolean result decisions flow through intermediate nodes // of different types based on relative estimates for sub-expressions @@ -53,12 +53,11 @@ concept DirectAdaptable = requires(const T &t) { auto make_adapter(const auto &children) { using type = std::remove_cvref_t<decltype(children)>::value_type; + static_assert(DefaultAdaptable<type> || DirectAdaptable<type>, "unable to resolve children adapter"); if constexpr (DefaultAdaptable<type>) { return DefaultAdapter(); - } else if constexpr (DirectAdaptable<type>) { - return DirectAdapter(); } else { - static_assert(false, "unable to resolve children adapter"); + return DirectAdapter(); } } @@ -280,4 +279,38 @@ public: } }; +using FlowCalc = std::function<double(double)>; + +template <typename FLOW> +FlowCalc flow_calc(bool strict, double non_strict_rate) { + FLOW flow = strict ? FLOW(true) : FLOW(non_strict_rate); + return [flow](double est) mutable noexcept { + double next_flow = flow.flow(); + flow.add(est); + return next_flow; + }; +} + +inline FlowCalc first_flow_calc(bool strict, double flow) { + if (strict) { + flow = 1.0; + } + bool first = true; + return [flow,first](double est) mutable noexcept { + double next_flow = flow; + if (first) { + flow *= est; + first = false; + } + return next_flow; + }; +} + +inline FlowCalc full_flow_calc(bool strict, double flow) { + if (strict) { + flow = 1.0; + } + return [flow](double) noexcept { return flow; }; +} + } diff --git a/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.cpp b/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.cpp index 993639becf2..6faa4ddf147 100644 --- a/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.cpp +++ b/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.cpp @@ -300,14 +300,10 @@ AndBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const return create_and_filter(get_children(), strict, constraint); } -double -AndBlueprint::computeNextHitRate(const Blueprint & child, double hit_rate) const { - return hit_rate * child.estimate(); -} - -double -OrBlueprint::computeNextHitRate(const Blueprint & child, double hit_rate) const { - return hit_rate * (1.0 - child.estimate()); +FlowCalc +AndBlueprint::make_flow_calc(bool strict, double flow) const +{ + return flow_calc<AndFlow>(strict, flow); } //----------------------------------------------------------------------------- @@ -404,6 +400,12 @@ OrBlueprint::createFilterSearch(bool strict, FilterConstraint constraint) const return create_or_filter(get_children(), strict, constraint); } +FlowCalc +OrBlueprint::make_flow_calc(bool strict, double flow) const +{ + return flow_calc<OrFlow>(strict, flow); +} + uint8_t OrBlueprint::calculate_cost_tier() const { diff --git a/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.h b/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.h index 1da70b4fa70..25586022535 100644 --- a/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.h +++ b/searchlib/src/vespa/searchlib/queryeval/intermediate_blueprints.h @@ -56,7 +56,7 @@ public: SearchIterator::UP createFilterSearch(bool strict, FilterConstraint constraint) const override; private: - double computeNextHitRate(const Blueprint & child, double hit_rate) const override; + virtual FlowCalc make_flow_calc(bool strict, double flow) const override; }; //----------------------------------------------------------------------------- @@ -81,7 +81,7 @@ public: SearchIterator::UP createFilterSearch(bool strict, FilterConstraint constraint) const override; private: - double computeNextHitRate(const Blueprint & child, double hit_rate) const override; + FlowCalc make_flow_calc(bool strict, double flow) const override; uint8_t calculate_cost_tier() const override; }; |