diff options
author | Dan Larkin-York <dan.larkin-york@mongodb.com> | 2023-02-03 23:42:29 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2023-02-04 01:32:37 +0000 |
commit | 94098eff431d7bb65da31516cc4df2a895d27dd8 (patch) | |
tree | 1aa862702400ebbf57026aa94e766b8d88b9e143 /src/mongo/db/exec | |
parent | 946646ef8d624116985f3acca5ec5ae359d59097 (diff) | |
download | mongo-94098eff431d7bb65da31516cc4df2a895d27dd8.tar.gz |
Revert "SERVER-71798 Expand the set of queries eligible for SBE in the 6.3 release"
Diffstat (limited to 'src/mongo/db/exec')
-rw-r--r-- | src/mongo/db/exec/plan_cache_util.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/exec/plan_cache_util.h | 54 | ||||
-rw-r--r-- | src/mongo/db/exec/sbe/expressions/expression.cpp | 16 | ||||
-rw-r--r-- | src/mongo/db/exec/sbe/values/value.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/exec/sbe/values/value.h | 13 | ||||
-rw-r--r-- | src/mongo/db/exec/sbe/values/value_printer.cpp | 6 | ||||
-rw-r--r-- | src/mongo/db/exec/sbe/vm/vm.cpp | 42 | ||||
-rw-r--r-- | src/mongo/db/exec/sbe/vm/vm.h | 6 | ||||
-rw-r--r-- | src/mongo/db/exec/sbe/vm/vm_printer.cpp | 36 |
9 files changed, 153 insertions, 26 deletions
diff --git a/src/mongo/db/exec/plan_cache_util.cpp b/src/mongo/db/exec/plan_cache_util.cpp index f223afc79f9..265eb1e70e7 100644 --- a/src/mongo/db/exec/plan_cache_util.cpp +++ b/src/mongo/db/exec/plan_cache_util.cpp @@ -76,7 +76,8 @@ void updatePlanCache(OperationContext* opCtx, const stage_builder::PlanStageData& data) { // TODO SERVER-67576: re-enable caching of "explode for sort" plans in the SBE cache. if (shouldCacheQuery(query) && collections.getMainCollection() && - !solution.hasExplodedForSort) { + !solution.hasExplodedForSort && + feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) { auto key = plan_cache_key_factory::make(query, collections); auto plan = std::make_unique<sbe::CachedSbePlan>(root.clone(), data); plan->indexFilterApplied = solution.indexFilterApplied; diff --git a/src/mongo/db/exec/plan_cache_util.h b/src/mongo/db/exec/plan_cache_util.h index 05b8e3d6a36..b233338882f 100644 --- a/src/mongo/db/exec/plan_cache_util.h +++ b/src/mongo/db/exec/plan_cache_util.h @@ -200,31 +200,35 @@ void updatePlanCache( if (winningPlan.solution->cacheData != nullptr) { if constexpr (std::is_same_v<PlanStageType, std::unique_ptr<sbe::PlanStage>>) { - tassert(6142201, - "The winning CandidatePlan should contain the original plan", - winningPlan.clonedPlan); - - // Clone the winning SBE plan and its auxiliary data. - auto cachedPlan = - std::make_unique<sbe::CachedSbePlan>(std::move(winningPlan.clonedPlan->first), - std::move(winningPlan.clonedPlan->second)); - cachedPlan->indexFilterApplied = winningPlan.solution->indexFilterApplied; - - auto buildDebugInfoFn = - [soln = winningPlan.solution.get()]() -> plan_cache_debug_info::DebugInfoSBE { - return buildDebugInfo(soln); - }; - PlanCacheCallbacksImpl<sbe::PlanCacheKey, - sbe::CachedSbePlan, - plan_cache_debug_info::DebugInfoSBE> - callbacks{query, buildDebugInfoFn}; - uassertStatusOK(sbe::getPlanCache(opCtx).set( - plan_cache_key_factory::make(query, collections), - std::move(cachedPlan), - *rankingDecision, - opCtx->getServiceContext()->getPreciseClockSource()->now(), - &callbacks, - boost::none /* worksGrowthCoefficient */)); + if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) { + tassert(6142201, + "The winning CandidatePlan should contain the original plan", + winningPlan.clonedPlan); + // Clone the winning SBE plan and its auxiliary data. + auto cachedPlan = std::make_unique<sbe::CachedSbePlan>( + std::move(winningPlan.clonedPlan->first), + std::move(winningPlan.clonedPlan->second)); + cachedPlan->indexFilterApplied = winningPlan.solution->indexFilterApplied; + + auto buildDebugInfoFn = [soln = winningPlan.solution.get()]() + -> plan_cache_debug_info::DebugInfoSBE { return buildDebugInfo(soln); }; + PlanCacheCallbacksImpl<sbe::PlanCacheKey, + sbe::CachedSbePlan, + plan_cache_debug_info::DebugInfoSBE> + callbacks{query, buildDebugInfoFn}; + uassertStatusOK(sbe::getPlanCache(opCtx).set( + plan_cache_key_factory::make(query, collections), + std::move(cachedPlan), + *rankingDecision, + opCtx->getServiceContext()->getPreciseClockSource()->now(), + &callbacks, + boost::none /* worksGrowthCoefficient */)); + } else { + // Fall back to use the classic plan cache. + // + // TODO SERVER-64882: Remove this branch after "gFeatureFlagSbeFull" is removed. + cacheClassicPlan(); + } } else { static_assert(std::is_same_v<PlanStageType, PlanStage*>); cacheClassicPlan(); diff --git a/src/mongo/db/exec/sbe/expressions/expression.cpp b/src/mongo/db/exec/sbe/expressions/expression.cpp index 26266070fa2..a96a559cd2d 100644 --- a/src/mongo/db/exec/sbe/expressions/expression.cpp +++ b/src/mongo/db/exec/sbe/expressions/expression.cpp @@ -933,6 +933,21 @@ vm::CodeFragment generateTraverseCellTypes(CompileCtx& ctx, return generatorLegacy<&vm::CodeFragment::appendTraverseCellTypes>(ctx, nodes, false); } +vm::CodeFragment generateClassicMatcher(CompileCtx& ctx, const EExpression::Vector& nodes, bool) { + tassert(6681400, + "First argument to applyClassicMatcher must be constant", + nodes[0]->as<EConstant>()); + auto [matcherTag, matcherVal] = nodes[0]->as<EConstant>()->getConstant(); + tassert(6681409, + "First argument to applyClassicMatcher must be a classic matcher", + matcherTag == value::TypeTags::classicMatchExpresion); + + vm::CodeFragment code; + code.append(nodes[1]->compileDirect(ctx)); + code.appendApplyClassicMatcher(value::getClassicMatchExpressionView(matcherVal)); + return code; +} + /** * The map of functions that resolve directly to instructions. */ @@ -971,6 +986,7 @@ static stdx::unordered_map<std::string, InstrFn> kInstrFunctions = { {"isMinKey", InstrFn{1, generator<1, &vm::CodeFragment::appendIsMinKey>, false}}, {"isMaxKey", InstrFn{1, generator<1, &vm::CodeFragment::appendIsMaxKey>, false}}, {"isTimestamp", InstrFn{1, generator<1, &vm::CodeFragment::appendIsTimestamp>, false}}, + {"applyClassicMatcher", InstrFn{2, generateClassicMatcher, false}}, }; } // namespace diff --git a/src/mongo/db/exec/sbe/values/value.cpp b/src/mongo/db/exec/sbe/values/value.cpp index a24883a7be9..e21bc694784 100644 --- a/src/mongo/db/exec/sbe/values/value.cpp +++ b/src/mongo/db/exec/sbe/values/value.cpp @@ -348,6 +348,9 @@ void releaseValueDeep(TypeTags tag, Value val) noexcept { case TypeTags::indexBounds: delete getIndexBoundsView(val); break; + case TypeTags::classicMatchExpresion: + delete getClassicMatchExpressionView(val); + break; default: break; } diff --git a/src/mongo/db/exec/sbe/values/value.h b/src/mongo/db/exec/sbe/values/value.h index 88cf3d3b011..0459118ddf1 100644 --- a/src/mongo/db/exec/sbe/values/value.h +++ b/src/mongo/db/exec/sbe/values/value.h @@ -191,6 +191,9 @@ enum class TypeTags : uint8_t { // Pointer to a IndexBounds object. indexBounds, + + // Pointer to a classic engine match expression. + classicMatchExpresion, }; inline constexpr bool isNumber(TypeTags tag) noexcept { @@ -1258,6 +1261,10 @@ inline IndexBounds* getIndexBoundsView(Value val) noexcept { return reinterpret_cast<IndexBounds*>(val); } +inline MatchExpression* getClassicMatchExpressionView(Value val) noexcept { + return reinterpret_cast<MatchExpression*>(val); +} + inline sbe::value::CsiCell* getCsiCellView(Value val) noexcept { return reinterpret_cast<sbe::value::CsiCell*>(val); } @@ -1472,6 +1479,12 @@ inline std::pair<TypeTags, Value> copyValue(TypeTags tag, Value val) { return makeCopyCollator(*getCollatorView(val)); case TypeTags::indexBounds: return makeCopyIndexBounds(*getIndexBoundsView(val)); + case TypeTags::classicMatchExpresion: + // Beware: "shallow cloning" a match expression does not copy the underlying BSON. The + // original BSON must remain alive for both the original MatchExpression and the clone. + return {TypeTags::classicMatchExpresion, + bitcastFrom<const MatchExpression*>( + getClassicMatchExpressionView(val)->shallowClone().release())}; default: break; } diff --git a/src/mongo/db/exec/sbe/values/value_printer.cpp b/src/mongo/db/exec/sbe/values/value_printer.cpp index 2405f698f3f..4cd70a9196b 100644 --- a/src/mongo/db/exec/sbe/values/value_printer.cpp +++ b/src/mongo/db/exec/sbe/values/value_printer.cpp @@ -163,6 +163,9 @@ void ValuePrinter<T>::writeTagToStream(TypeTags tag) { case TypeTags::indexBounds: stream << "indexBounds"; break; + case TypeTags::classicMatchExpresion: + stream << "classicMatchExpression"; + break; case TypeTags::csiCell: stream << "csiCell"; break; @@ -536,6 +539,9 @@ void ValuePrinter<T>::writeValueToStream(TypeTags tag, Value val, size_t depth) getIndexBoundsView(val)->toString(true /* hasNonSimpleCollation */)); stream << ")"; break; + case TypeTags::classicMatchExpresion: + stream << "ClassicMatcher(" << getClassicMatchExpressionView(val)->toString() << ")"; + break; case TypeTags::csiCell: stream << "CsiCell(" << getCsiCellView(val) << ")"; break; diff --git a/src/mongo/db/exec/sbe/vm/vm.cpp b/src/mongo/db/exec/sbe/vm/vm.cpp index 35dab757964..3a8e48daf0a 100644 --- a/src/mongo/db/exec/sbe/vm/vm.cpp +++ b/src/mongo/db/exec/sbe/vm/vm.cpp @@ -166,6 +166,7 @@ int Instruction::stackOffset[Instruction::Tags::lastInstruction] = { -1, // fail + 0, // applyClassicMatcher 0, // dateTruncImm }; @@ -481,6 +482,18 @@ void CodeFragment::appendNumericConvert(value::TypeTags targetTag) { adjustStackSimple(i); } +void CodeFragment::appendApplyClassicMatcher(const MatchExpression* matcher) { + Instruction i; + i.tag = Instruction::applyClassicMatcher; + + auto offset = allocateSpace(sizeof(Instruction) + sizeof(matcher)); + + offset += writeToMemory(offset, i); + offset += writeToMemory(offset, matcher); + + adjustStackSimple(i); +} + void CodeFragment::appendSub(Instruction::Parameter lhs, Instruction::Parameter rhs) { appendSimpleInstruction(Instruction::sub, lhs, rhs); } @@ -5737,6 +5750,28 @@ MONGO_COMPILER_NORETURN void ByteCode::runFailInstruction() { uasserted(code, message); } + +void ByteCode::runClassicMatcher(const MatchExpression* matcher) { + auto [ownedObj, tagObj, valObj] = getFromStack(0); + + BSONObj bsonObjForMatching; + if (tagObj == value::TypeTags::Object) { + BSONObjBuilder builder; + sbe::bson::convertToBsonObj(builder, sbe::value::getObjectView(valObj)); + bsonObjForMatching = builder.obj(); + } else if (tagObj == value::TypeTags::bsonObject) { + auto bson = value::getRawPointerView(valObj); + bsonObjForMatching = BSONObj(bson); + } else { + MONGO_UNREACHABLE_TASSERT(6681402); + } + + bool res = matcher->matchesBSON(bsonObjForMatching); + if (ownedObj) { + value::releaseValue(tagObj, valObj); + } + topStack(false, value::TypeTags::Boolean, value::bitcastFrom<bool>(res)); +} template <typename T> void ByteCode::runTagCheck(const uint8_t*& pcPointer, T&& predicate) { auto [popParam, offsetParam] = decodeParam(pcPointer); @@ -6747,6 +6782,13 @@ void ByteCode::runInternal(const CodeFragment* code, int64_t position) { runFailInstruction(); break; } + case Instruction::applyClassicMatcher: { + const auto* matcher = readFromMemory<const MatchExpression*>(pcPointer); + pcPointer += sizeof(matcher); + + runClassicMatcher(matcher); + break; + } case Instruction::dateTruncImm: { auto unit = readFromMemory<TimeUnit>(pcPointer); pcPointer += sizeof(unit); diff --git a/src/mongo/db/exec/sbe/vm/vm.h b/src/mongo/db/exec/sbe/vm/vm.h index 7034e1fabfe..b6ee6d2dc75 100644 --- a/src/mongo/db/exec/sbe/vm/vm.h +++ b/src/mongo/db/exec/sbe/vm/vm.h @@ -349,6 +349,8 @@ struct Instruction { fail, + applyClassicMatcher, // Instruction which calls into the classic engine MatchExpression. + dateTruncImm, lastInstruction // this is just a marker used to calculate number of instructions @@ -575,6 +577,8 @@ struct Instruction { return "allocStack"; case fail: return "fail"; + case applyClassicMatcher: + return "applyClassicMatcher"; case dateTruncImm: return "dateTruncImm"; default: @@ -886,6 +890,7 @@ public: void appendAllocStack(uint32_t size); void appendFail(); void appendNumericConvert(value::TypeTags targetTag); + void appendApplyClassicMatcher(const MatchExpression*); // For printing from an interactive debugger. std::string toString() const; @@ -994,6 +999,7 @@ private: void runLambdaInternal(const CodeFragment* code, int64_t position); MONGO_COMPILER_NORETURN void runFailInstruction(); + void runClassicMatcher(const MatchExpression* matcher); template <typename T> void runTagCheck(const uint8_t*& pcPointer, T&& predicate); diff --git a/src/mongo/db/exec/sbe/vm/vm_printer.cpp b/src/mongo/db/exec/sbe/vm/vm_printer.cpp index 85c59dc9957..8ac6fe532c2 100644 --- a/src/mongo/db/exec/sbe/vm/vm_printer.cpp +++ b/src/mongo/db/exec/sbe/vm/vm_printer.cpp @@ -49,6 +49,10 @@ struct CodeFragmentFormatter<CodeFragmentPrinter::PrintFormat::Debug> { return SlotAccessorFmt{accessor}; } + auto matchExpression(const MatchExpression* matcher) { + return MatchExpressionFmt{matcher}; + } + struct PcPointerFmt { const uint8_t* pcPointer; }; @@ -56,6 +60,10 @@ struct CodeFragmentFormatter<CodeFragmentPrinter::PrintFormat::Debug> { struct SlotAccessorFmt { value::SlotAccessor* accessor; }; + + struct MatchExpressionFmt { + const MatchExpression* matcher; + }; }; template <typename charT, typename traits> @@ -72,6 +80,13 @@ std::basic_ostream<charT, traits>& operator<<( return os << static_cast<const void*>(a.accessor); } +template <typename charT, typename traits> +std::basic_ostream<charT, traits>& operator<<( + std::basic_ostream<charT, traits>& os, + const CodeFragmentFormatter<CodeFragmentPrinter::PrintFormat::Debug>::MatchExpressionFmt& a) { + return os << static_cast<const void*>(a.matcher); +} + template <> struct CodeFragmentFormatter<CodeFragmentPrinter::PrintFormat::Stable> { CodeFragmentFormatter(const CodeFragment& code) : code(code) {} @@ -84,6 +99,10 @@ struct CodeFragmentFormatter<CodeFragmentPrinter::PrintFormat::Stable> { return SlotAccessorFmt{accessor}; } + auto matchExpression(const MatchExpression* matcher) { + return MatchExpressionFmt{matcher}; + } + struct PcPointerFmt { const uint8_t* pcPointer; const uint8_t* pcBegin; @@ -93,6 +112,10 @@ struct CodeFragmentFormatter<CodeFragmentPrinter::PrintFormat::Stable> { value::SlotAccessor* accessor; }; + struct MatchExpressionFmt { + const MatchExpression* matcher; + }; + const CodeFragment& code; }; @@ -114,6 +137,13 @@ std::basic_ostream<charT, traits>& operator<<( return os << "<accessor>"; } +template <typename charT, typename traits> +std::basic_ostream<charT, traits>& operator<<( + std::basic_ostream<charT, traits>& os, + const CodeFragmentFormatter<CodeFragmentPrinter::PrintFormat::Stable>::MatchExpressionFmt& a) { + return os << "<matchExpression>"; +} + template <typename Formatter> class CodeFragmentPrinterImpl { public: @@ -298,6 +328,12 @@ public: os << "accessor: " << _formatter.slotAccessor(accessor); break; } + case Instruction::applyClassicMatcher: { + const auto* matcher = readFromMemory<const MatchExpression*>(pcPointer); + pcPointer += sizeof(matcher); + os << "matcher: " << _formatter.matchExpression(matcher); + break; + } case Instruction::numConvert: { auto tag = readFromMemory<value::TypeTags>(pcPointer); pcPointer += sizeof(tag); |