diff options
author | Ruoxin Xu <ruoxin.xu@mongodb.com> | 2022-03-15 16:07:38 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-03-15 17:29:38 +0000 |
commit | c51987df9a8b60a98e9f91ff0328208df60427f8 (patch) | |
tree | ff075abdb2120bcb21b096cd5cb263a01c751c1f | |
parent | 63a4f1e011860e34b8a29b6171e3cbdd58f15c8d (diff) | |
download | mongo-c51987df9a8b60a98e9f91ff0328208df60427f8.tar.gz |
SERVER-64074 Optimize how we build the DebugInfo for plan cache
-rw-r--r-- | src/mongo/db/commands/index_filter_commands_test.cpp | 12 | ||||
-rw-r--r-- | src/mongo/db/exec/plan_cache_util.h | 32 | ||||
-rw-r--r-- | src/mongo/db/query/plan_cache.h | 23 | ||||
-rw-r--r-- | src/mongo/db/query/plan_cache_callbacks.h | 15 | ||||
-rw-r--r-- | src/mongo/db/query/plan_cache_test.cpp | 400 |
5 files changed, 162 insertions, 320 deletions
diff --git a/src/mongo/db/commands/index_filter_commands_test.cpp b/src/mongo/db/commands/index_filter_commands_test.cpp index 194bcaed8ae..5cea275b5a8 100644 --- a/src/mongo/db/commands/index_filter_commands_test.cpp +++ b/src/mongo/db/commands/index_filter_commands_test.cpp @@ -151,15 +151,17 @@ void addQueryShapeToPlanCache(OperationContext* opCtx, cacheData->tree = std::make_unique<PlanCacheIndexTree>(); auto decision = createDecision(1U); auto decisionPtr = decision.get(); - PlanCacheLoggingCallbacks<PlanCacheKey, SolutionCacheData, plan_cache_debug_info::DebugInfo> - callbacks{*cq}; + auto buildDebugInfoFn = [&]() -> plan_cache_debug_info::DebugInfo { + return plan_cache_util::buildDebugInfo(*cq, std::move(decision)); + }; + PlanCacheCallbacksImpl<PlanCacheKey, SolutionCacheData, plan_cache_debug_info::DebugInfo> + callbacks{*cq, buildDebugInfoFn}; ASSERT_OK(planCache->set(makeKey(*cq), std::move(cacheData), *decisionPtr, opCtx->getServiceContext()->getPreciseClockSource()->now(), - plan_cache_util::buildDebugInfo(*cq, std::move(decision)), - boost::none, /* worksGrowthCoefficient */ - &callbacks)); + &callbacks, + boost::none /* worksGrowthCoefficient */)); } /** diff --git a/src/mongo/db/exec/plan_cache_util.h b/src/mongo/db/exec/plan_cache_util.h index 9b3d4b540cb..4c5249cb1e6 100644 --- a/src/mongo/db/exec/plan_cache_util.h +++ b/src/mongo/db/exec/plan_cache_util.h @@ -181,19 +181,21 @@ void updatePlanCache( if (shouldCacheQuery(query) && canCache) { auto rankingDecision = ranking.get(); auto cacheClassicPlan = [&]() { - PlanCacheLoggingCallbacks<PlanCacheKey, - SolutionCacheData, - plan_cache_debug_info::DebugInfo> - callbacks{query}; + auto buildDebugInfoFn = [&]() -> plan_cache_debug_info::DebugInfo { + return buildDebugInfo(query, std::move(ranking)); + }; + PlanCacheCallbacksImpl<PlanCacheKey, + SolutionCacheData, + plan_cache_debug_info::DebugInfo> + callbacks{query, buildDebugInfoFn}; uassertStatusOK(CollectionQueryInfo::get(collection) .getPlanCache() ->set(plan_cache_key_factory::make<PlanCacheKey>(query, collection), winningPlan.solution->cacheData->clone(), *rankingDecision, opCtx->getServiceContext()->getPreciseClockSource()->now(), - buildDebugInfo(query, std::move(ranking)), - boost::none, /* worksGrowthCoefficient */ - &callbacks)); + &callbacks, + boost::none /* worksGrowthCoefficient */)); }; if (winningPlan.solution->cacheData != nullptr) { @@ -206,19 +208,19 @@ void updatePlanCache( auto cachedPlan = std::make_unique<sbe::CachedSbePlan>( std::move(winningPlan.clonedPlan->first), std::move(winningPlan.clonedPlan->second)); - - PlanCacheLoggingCallbacks<sbe::PlanCacheKey, - sbe::CachedSbePlan, - plan_cache_debug_info::DebugInfoSBE> - callbacks{query}; + 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<sbe::PlanCacheKey>(query, collection), std::move(cachedPlan), *rankingDecision, opCtx->getServiceContext()->getPreciseClockSource()->now(), - buildDebugInfo(winningPlan.solution.get()), - boost::none, /* worksGrowthCoefficient */ - &callbacks)); + &callbacks, + boost::none /* worksGrowthCoefficient */)); } else { // Fall back to use the classic plan cache. Remove this branch after // "gFeatureFlagSbePlanCache" is removed. diff --git a/src/mongo/db/query/plan_cache.h b/src/mongo/db/query/plan_cache.h index 22111148c0f..d8b0bc5b3f4 100644 --- a/src/mongo/db/query/plan_cache.h +++ b/src/mongo/db/query/plan_cache.h @@ -335,19 +335,18 @@ public: * an inactive cache entry. If boost::none is provided, the function will use * 'internalQueryCacheWorksGrowthCoefficient'. * - * A 'callbacks' argument can be provided to perform some custom actions when the state of the - * plan cache or a plan cache entry has been changed. + * A 'callbacks' argument should be provided to perform some custom actions when the state of + * the plan cache or a plan cache entry has been changed. The 'callbacks' is also responsible + * for constructing DebugInfo. * * If the mapping was set successfully, returns Status::OK(), even if it evicted another entry. */ - Status set( - const KeyType& key, - std::unique_ptr<CachedPlanType> cachedPlan, - const plan_ranker::PlanRankingDecision& why, - Date_t now, - DebugInfoType debugInfo, - boost::optional<double> worksGrowthCoefficient = boost::none, - const PlanCacheCallbacks<KeyType, CachedPlanType, DebugInfoType>* callbacks = nullptr) { + Status set(const KeyType& key, + std::unique_ptr<CachedPlanType> cachedPlan, + const plan_ranker::PlanRankingDecision& why, + Date_t now, + const PlanCacheCallbacks<KeyType, CachedPlanType, DebugInfoType>* callbacks, + boost::optional<double> worksGrowthCoefficient = boost::none) { invariant(cachedPlan); if (why.scores.size() != why.candidateOrder.size()) { @@ -405,13 +404,15 @@ public: return Status::OK(); } + // We use callback function here to build the 'DebugInfo' rather than pass in a constructed + // DebugInfo for performance. auto newEntry(Entry::create(std::move(cachedPlan), queryHash, planCacheKey, now, isNewEntryActive, newWorks, - std::move(debugInfo))); + callbacks->buildDebugInfo())); partition->add(key, newEntry.release()); return Status::OK(); diff --git a/src/mongo/db/query/plan_cache_callbacks.h b/src/mongo/db/query/plan_cache_callbacks.h index ece4796b74b..f33a7d3b407 100644 --- a/src/mongo/db/query/plan_cache_callbacks.h +++ b/src/mongo/db/query/plan_cache_callbacks.h @@ -98,16 +98,19 @@ public: const KeyType& key, const PlanCacheEntryBase<CachedPlanType, DebugInfoType>* oldEntry, size_t newWorks) const = 0; + virtual DebugInfoType buildDebugInfo() const = 0; }; /** * Simple logging callbacks for the plan cache. */ template <typename KeyType, typename CachedPlanType, typename DebugInfoType> -class PlanCacheLoggingCallbacks - : public PlanCacheCallbacks<KeyType, CachedPlanType, DebugInfoType> { +class PlanCacheCallbacksImpl : public PlanCacheCallbacks<KeyType, CachedPlanType, DebugInfoType> { public: - PlanCacheLoggingCallbacks(const CanonicalQuery& cq) : _cq{cq} {} + PlanCacheCallbacksImpl(const CanonicalQuery& cq) : _cq{cq} {} + + PlanCacheCallbacksImpl(const CanonicalQuery& cq, std::function<DebugInfoType()> buildDebugInfo) + : _cq{cq}, _buildDebugInfoCallBack(buildDebugInfo) {} void onCreateInactiveCacheEntry( const KeyType& key, @@ -171,6 +174,11 @@ public: newWorks); } + DebugInfoType buildDebugInfo() const final { + tassert(6407401, "_buildDebugInfoCallBack should be callable", _buildDebugInfoCallBack); + return _buildDebugInfoCallBack(); + } + private: auto hashes(const KeyType& key, const PlanCacheEntryBase<CachedPlanType, DebugInfoType>* oldEntry) const { @@ -182,5 +190,6 @@ private: } const CanonicalQuery& _cq; + std::function<DebugInfoType()> _buildDebugInfoCallBack; }; } // namespace mongo diff --git a/src/mongo/db/query/plan_cache_test.cpp b/src/mongo/db/query/plan_cache_test.cpp index d69260b50a7..e3120290ecf 100644 --- a/src/mongo/db/query/plan_cache_test.cpp +++ b/src/mongo/db/query/plan_cache_test.cpp @@ -305,17 +305,21 @@ TEST(PlanCacheTest, ShouldNotCacheQueryExplain) { assertShouldNotCacheQuery(*cq); } +PlanCacheCallbacksImpl<PlanCacheKey, SolutionCacheData, plan_cache_debug_info::DebugInfo> +createCallback(const CanonicalQuery& cq, const plan_ranker::PlanRankingDecision& decision) { + auto buildDebugInfoFn = [&]() -> plan_cache_debug_info::DebugInfo { + return plan_cache_util::buildDebugInfo(cq, decision.clone()); + }; + return {cq, std::move(buildDebugInfoFn)}; +} + void addCacheEntryForShape(const CanonicalQuery& cq, PlanCache* planCache) { invariant(planCache); auto qs = getQuerySolutionForCaching(); auto decision = createDecision(1U); - auto decisionPtr = decision.get(); - ASSERT_OK(planCache->set(makeKey(cq), - qs->cacheData->clone(), - *decisionPtr, - Date_t{}, - plan_cache_util::buildDebugInfo(cq, std::move(decision)))); + auto callbacks = createCallback(cq, *decision); + ASSERT_OK(planCache->set(makeKey(cq), qs->cacheData->clone(), *decision, Date_t{}, &callbacks)); } TEST(PlanCacheTest, InactiveEntriesDisabled) { @@ -328,15 +332,11 @@ TEST(PlanCacheTest, InactiveEntriesDisabled) { auto qs = getQuerySolutionForCaching(); auto key = makeKey(*cq); auto decision = createDecision(1U); - auto decisionPtr = decision.get(); + auto callbacks = createCallback(*cq, *decision); ASSERT_EQ(planCache.get(key).state, PlanCache::CacheEntryState::kNotPresent); QueryTestServiceContext serviceContext; - ASSERT_OK(planCache.set(makeKey(*cq), - qs->cacheData->clone(), - *decisionPtr, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decision)))); + ASSERT_OK(planCache.set(makeKey(*cq), qs->cacheData->clone(), *decision, Date_t{}, &callbacks)); // After add, the planCache should have an _active_ entry. ASSERT_EQ(planCache.get(key).state, PlanCache::CacheEntryState::kPresentActive); @@ -396,14 +396,10 @@ TEST(PlanCacheTest, PlanCacheRemoveDeletesInactiveEntries) { auto key = makeKey(*cq); auto decision = createDecision(1U); - auto decisionPtr = decision.get(); + auto callbacks = createCallback(*cq, *decision); ASSERT_EQ(planCache.get(key).state, PlanCache::CacheEntryState::kNotPresent); QueryTestServiceContext serviceContext; - ASSERT_OK(planCache.set(makeKey(*cq), - qs->cacheData->clone(), - *decisionPtr, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decision)))); + ASSERT_OK(planCache.set(makeKey(*cq), qs->cacheData->clone(), *decision, Date_t{}, &callbacks)); // After add, the planCache should have an inactive entry. ASSERT_EQ(planCache.get(key).state, PlanCache::CacheEntryState::kPresentInactive); @@ -421,14 +417,10 @@ TEST(PlanCacheTest, PlanCacheFlushDeletesInactiveEntries) { auto key = makeKey(*cq); auto decision = createDecision(1U); - auto decisionPtr = decision.get(); + auto callbacks = createCallback(*cq, *decision); ASSERT_EQ(planCache.get(key).state, PlanCache::CacheEntryState::kNotPresent); QueryTestServiceContext serviceContext; - ASSERT_OK(planCache.set(makeKey(*cq), - qs->cacheData->clone(), - *decisionPtr, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decision)))); + ASSERT_OK(planCache.set(makeKey(*cq), qs->cacheData->clone(), *decision, Date_t{}, &callbacks)); // After add, the planCache should have an inactive entry. ASSERT_EQ(planCache.get(key).state, PlanCache::CacheEntryState::kPresentInactive); @@ -446,28 +438,21 @@ TEST(PlanCacheTest, AddActiveCacheEntry) { auto key = makeKey(*cq); auto decision = createDecision(1U, 20); - auto decisionPtr = decision.get(); + auto callbacks = createCallback(*cq, *decision); // Check if key is in cache before and after set(). ASSERT_EQ(planCache.get(key).state, PlanCache::CacheEntryState::kNotPresent); QueryTestServiceContext serviceContext; - ASSERT_OK(planCache.set(makeKey(*cq), - qs->cacheData->clone(), - *decisionPtr, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decision)))); + ASSERT_OK(planCache.set(makeKey(*cq), qs->cacheData->clone(), *decision, Date_t{}, &callbacks)); // After add, the planCache should have an inactive entry. ASSERT_EQ(planCache.get(key).state, PlanCache::CacheEntryState::kPresentInactive); decision = createDecision(1U, 10); - decisionPtr = decision.get(); + auto callbacks1 = createCallback(*cq, *decision); // Calling set() again, with a solution that had a lower works value should create an active // entry. - ASSERT_OK(planCache.set(makeKey(*cq), - qs->cacheData->clone(), - *decisionPtr, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decision)))); + ASSERT_OK( + planCache.set(makeKey(*cq), qs->cacheData->clone(), *decision, Date_t{}, &callbacks1)); ASSERT_EQ(planCache.get(key).state, PlanCache::CacheEntryState::kPresentActive); ASSERT_EQUALS(planCache.size(), 1U); @@ -482,22 +467,12 @@ TEST(PlanCacheTest, WorksValueIncreases) { unique_ptr<CanonicalQuery> cq(canonicalize("{a: 1}")); auto qs = getQuerySolutionForCaching(); auto key = makeKey(*cq); - auto decisionPtr = createDecision(1U, 10); - auto decision = decisionPtr.get(); - PlanCacheLoggingCallbacks<PlanCacheKey, - SolutionCacheData, - mongo::plan_cache_debug_info::DebugInfo> - callbacks{*cq}; + auto decision = createDecision(1U, 10); + auto callbacks = createCallback(*cq, *decision); ASSERT_EQ(planCache.get(key).state, PlanCache::CacheEntryState::kNotPresent); QueryTestServiceContext serviceContext; - ASSERT_OK(planCache.set(key, - qs->cacheData->clone(), - *decision, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decisionPtr)), - boost::none /* worksGrowthCoefficient */, - &callbacks)); + ASSERT_OK(planCache.set(key, qs->cacheData->clone(), *decision, Date_t{}, &callbacks)); // After add, the planCache should have an inactive entry. ASSERT_EQ(planCache.get(key).state, PlanCache::CacheEntryState::kPresentInactive); @@ -506,15 +481,12 @@ TEST(PlanCacheTest, WorksValueIncreases) { ASSERT_EQ(entry->works.get(), 10U); ASSERT_FALSE(entry->isActive); - decisionPtr = createDecision(1U, 50); - decision = decisionPtr.get(); + decision = createDecision(1U, 50); + auto callbacks1 = createCallback(*cq, *decision); // Calling set() again, with a solution that had a higher works value. This should cause the // works on the original entry to be increased. - ASSERT_OK(planCache.set(makeKey(*cq), - qs->cacheData->clone(), - *decision, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decisionPtr)))); + ASSERT_OK( + planCache.set(makeKey(*cq), qs->cacheData->clone(), *decision, Date_t{}, &callbacks1)); // The entry should still be inactive. Its works should double though. ASSERT_EQ(planCache.get(key).state, PlanCache::CacheEntryState::kPresentInactive); @@ -523,15 +495,12 @@ TEST(PlanCacheTest, WorksValueIncreases) { ASSERT_TRUE(entry->works); ASSERT_EQ(entry->works.get(), 20U); - decisionPtr = createDecision(1U, 30); - decision = decisionPtr.get(); + decision = createDecision(1U, 30); + auto callbacks2 = createCallback(*cq, *decision); // Calling set() again, with a solution that had a higher works value. This should cause the // works on the original entry to be increased. - ASSERT_OK(planCache.set(makeKey(*cq), - qs->cacheData->clone(), - *decision, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decisionPtr)))); + ASSERT_OK( + planCache.set(makeKey(*cq), qs->cacheData->clone(), *decision, Date_t{}, &callbacks2)); // The entry should still be inactive. Its works should have doubled again. ASSERT_EQ(planCache.get(key).state, PlanCache::CacheEntryState::kPresentInactive); @@ -540,17 +509,11 @@ TEST(PlanCacheTest, WorksValueIncreases) { ASSERT_TRUE(entry->works); ASSERT_EQ(entry->works.get(), 40U); - decisionPtr = createDecision(1U, 25); - decision = decisionPtr.get(); + decision = createDecision(1U, 25); + auto callbacks3 = createCallback(*cq, *decision); // Calling set() again, with a solution that has a lower works value than what's currently in // the cache. - ASSERT_OK(planCache.set(key, - qs->cacheData->clone(), - *decision, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decisionPtr)), - boost::none /* worksGrowthCoefficient */, - &callbacks)); + ASSERT_OK(planCache.set(key, qs->cacheData->clone(), *decision, Date_t{}, &callbacks3)); // The solution just run should now be in an active cache entry, with a works // equal to the number of works the solution took. @@ -582,15 +545,11 @@ TEST(PlanCacheTest, WorksValueIncreasesByAtLeastOne) { auto qs = getQuerySolutionForCaching(); auto key = makeKey(*cq); auto decision = createDecision(1U, 3); - auto decisionPtr = decision.get(); + auto callbacks = createCallback(*cq, *decision); ASSERT_EQ(planCache.get(key).state, PlanCache::CacheEntryState::kNotPresent); QueryTestServiceContext serviceContext; - ASSERT_OK(planCache.set(makeKey(*cq), - qs->cacheData->clone(), - *decisionPtr, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decision)))); + ASSERT_OK(planCache.set(makeKey(*cq), qs->cacheData->clone(), *decision, Date_t{}, &callbacks)); // After add, the planCache should have an inactive entry. ASSERT_EQ(planCache.get(key).state, PlanCache::CacheEntryState::kPresentInactive); @@ -600,17 +559,13 @@ TEST(PlanCacheTest, WorksValueIncreasesByAtLeastOne) { ASSERT_FALSE(entry->isActive); decision = createDecision(1U, 50); - decisionPtr = decision.get(); + auto callbacks1 = createCallback(*cq, *decision); // Calling set() again, with a solution that had a higher works value. This should cause the // works on the original entry to be increased. In this case, since nWorks is 3, // multiplying by the value 1.10 will give a value of 3 (static_cast<size_t>(1.1 * 3) == 3). // We check that the works value is increased 1 instead. - ASSERT_OK(planCache.set(makeKey(*cq), - qs->cacheData->clone(), - *decisionPtr, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decision)), - kWorksCoeff)); + ASSERT_OK(planCache.set( + makeKey(*cq), qs->cacheData->clone(), *decision, Date_t{}, &callbacks1, kWorksCoeff)); // The entry should still be inactive. Its works should increase by 1. ASSERT_EQ(planCache.get(key).state, PlanCache::CacheEntryState::kPresentInactive); @@ -631,15 +586,11 @@ TEST(PlanCacheTest, SetIsNoopWhenNewEntryIsWorse) { auto qs = getQuerySolutionForCaching(); auto key = makeKey(*cq); auto decision = createDecision(1U, 50); - auto decisionPtr = decision.get(); + auto callbacks = createCallback(*cq, *decision); ASSERT_EQ(planCache.get(key).state, PlanCache::CacheEntryState::kNotPresent); QueryTestServiceContext serviceContext; - ASSERT_OK(planCache.set(makeKey(*cq), - qs->cacheData->clone(), - *decisionPtr, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decision)))); + ASSERT_OK(planCache.set(makeKey(*cq), qs->cacheData->clone(), *decision, Date_t{}, &callbacks)); // After add, the planCache should have an inactive entry. ASSERT_EQ(planCache.get(key).state, PlanCache::CacheEntryState::kPresentInactive); @@ -649,14 +600,11 @@ TEST(PlanCacheTest, SetIsNoopWhenNewEntryIsWorse) { ASSERT_FALSE(entry->isActive); decision = createDecision(1U, 20); - decisionPtr = decision.get(); + auto callbacks1 = createCallback(*cq, *decision); // Call set() again, with a solution that has a lower works value. This will result in an // active entry being created. - ASSERT_OK(planCache.set(makeKey(*cq), - qs->cacheData->clone(), - *decisionPtr, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decision)))); + ASSERT_OK( + planCache.set(makeKey(*cq), qs->cacheData->clone(), *decision, Date_t{}, &callbacks1)); ASSERT_EQ(planCache.get(key).state, PlanCache::CacheEntryState::kPresentActive); entry = assertGet(planCache.getEntry(key)); ASSERT_TRUE(entry->isActive); @@ -664,14 +612,11 @@ TEST(PlanCacheTest, SetIsNoopWhenNewEntryIsWorse) { ASSERT_EQ(entry->works.get(), 20U); decision = createDecision(1U, 100); - decisionPtr = decision.get(); + auto callbacks2 = createCallback(*cq, *decision); // Now call set() again, but with a solution that has a higher works value. This should be // a noop. - ASSERT_OK(planCache.set(makeKey(*cq), - qs->cacheData->clone(), - *decisionPtr, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decision)))); + ASSERT_OK( + planCache.set(makeKey(*cq), qs->cacheData->clone(), *decision, Date_t{}, &callbacks2)); ASSERT_EQ(planCache.get(key).state, PlanCache::CacheEntryState::kPresentActive); entry = assertGet(planCache.getEntry(key)); ASSERT_TRUE(entry->isActive); @@ -686,14 +631,10 @@ TEST(PlanCacheTest, SetOverwritesWhenNewEntryIsBetter) { auto key = makeKey(*cq); auto decision = createDecision(1U, 50); - auto decisionPtr = decision.get(); + auto callbacks = createCallback(*cq, *decision); ASSERT_EQ(planCache.get(key).state, PlanCache::CacheEntryState::kNotPresent); QueryTestServiceContext serviceContext; - ASSERT_OK(planCache.set(makeKey(*cq), - qs->cacheData->clone(), - *decisionPtr, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decision)))); + ASSERT_OK(planCache.set(makeKey(*cq), qs->cacheData->clone(), *decision, Date_t{}, &callbacks)); // After add, the planCache should have an inactive entry. auto entry = assertGet(planCache.getEntry(key)); @@ -702,14 +643,11 @@ TEST(PlanCacheTest, SetOverwritesWhenNewEntryIsBetter) { ASSERT_FALSE(entry->isActive); decision = createDecision(1U, 20); - decisionPtr = decision.get(); + auto callbacks1 = createCallback(*cq, *decision); // Call set() again, with a solution that has a lower works value. This will result in an // active entry being created. - ASSERT_OK(planCache.set(makeKey(*cq), - qs->cacheData->clone(), - *decisionPtr, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decision)))); + ASSERT_OK( + planCache.set(makeKey(*cq), qs->cacheData->clone(), *decision, Date_t{}, &callbacks1)); ASSERT_EQ(planCache.get(key).state, PlanCache::CacheEntryState::kPresentActive); entry = assertGet(planCache.getEntry(key)); ASSERT_TRUE(entry->isActive); @@ -717,14 +655,11 @@ TEST(PlanCacheTest, SetOverwritesWhenNewEntryIsBetter) { ASSERT_EQ(entry->works.get(), 20U); decision = createDecision(1U, 10); - decisionPtr = decision.get(); + auto callbacks2 = createCallback(*cq, *decision); // Now call set() again, with a solution that has a lower works value. The current active entry // should be overwritten. - ASSERT_OK(planCache.set(makeKey(*cq), - qs->cacheData->clone(), - *decisionPtr, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decision)))); + ASSERT_OK( + planCache.set(makeKey(*cq), qs->cacheData->clone(), *decision, Date_t{}, &callbacks2)); ASSERT_EQ(planCache.get(key).state, PlanCache::CacheEntryState::kPresentActive); entry = assertGet(planCache.getEntry(key)); ASSERT_TRUE(entry->isActive); @@ -738,15 +673,11 @@ TEST(PlanCacheTest, DeactivateCacheEntry) { auto qs = getQuerySolutionForCaching(); auto key = makeKey(*cq); auto decision = createDecision(1U, 50); - auto decisionPtr = decision.get(); + auto callbacks = createCallback(*cq, *decision); ASSERT_EQ(planCache.get(key).state, PlanCache::CacheEntryState::kNotPresent); QueryTestServiceContext serviceContext; - ASSERT_OK(planCache.set(makeKey(*cq), - qs->cacheData->clone(), - *decisionPtr, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decision)))); + ASSERT_OK(planCache.set(makeKey(*cq), qs->cacheData->clone(), *decision, Date_t{}, &callbacks)); // After add, the planCache should have an inactive entry. auto entry = assertGet(planCache.getEntry(key)); @@ -755,14 +686,11 @@ TEST(PlanCacheTest, DeactivateCacheEntry) { ASSERT_FALSE(entry->isActive); decision = createDecision(1U, 20); - decisionPtr = decision.get(); + auto callbacks1 = createCallback(*cq, *decision); // Call set() again, with a solution that has a lower works value. This will result in an // active entry being created. - ASSERT_OK(planCache.set(makeKey(*cq), - qs->cacheData->clone(), - *decisionPtr, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decision)))); + ASSERT_OK( + planCache.set(makeKey(*cq), qs->cacheData->clone(), *decision, Date_t{}, &callbacks1)); ASSERT_EQ(planCache.get(key).state, PlanCache::CacheEntryState::kPresentActive); entry = assertGet(planCache.getEntry(key)); ASSERT_TRUE(entry->isActive); @@ -787,25 +715,19 @@ TEST(PlanCacheTest, GetMatchingStatsMatchesAndSerializesCorrectly) { unique_ptr<CanonicalQuery> cq(canonicalize("{a: 1}")); auto qs = getQuerySolutionForCaching(); auto decision = createDecision(1U, 5); - auto decisionPtr = decision.get(); - ASSERT_OK(planCache.set(makeKey(*cq), - qs->cacheData->clone(), - *decisionPtr, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decision)))); + auto callbacks = createCallback(*cq, *decision); + ASSERT_OK( + planCache.set(makeKey(*cq), qs->cacheData->clone(), *decision, Date_t{}, &callbacks)); } // Create a second cache entry with 3 works. { - auto decision = createDecision(1U, 3); unique_ptr<CanonicalQuery> cq(canonicalize("{b: 1}")); auto qs = getQuerySolutionForCaching(); - auto decisionPtr = decision.get(); - ASSERT_OK(planCache.set(makeKey(*cq), - qs->cacheData->clone(), - *decisionPtr, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decision)))); + auto decision = createDecision(1U, 3); + auto callbacks = createCallback(*cq, *decision); + ASSERT_OK( + planCache.set(makeKey(*cq), qs->cacheData->clone(), *decision, Date_t{}, &callbacks)); } // Verify that the cache entries have been created. @@ -1796,60 +1718,32 @@ TEST(PlanCacheTest, PlanCacheSizeWithCRUDOperations) { auto qs = getQuerySolutionForCaching(); long long previousSize, originalSize = planCacheTotalSizeEstimateBytes.get(); auto key = makeKey(*cq); - auto decisionPtr = createDecision(1U); - auto decision = decisionPtr.get(); - PlanCacheLoggingCallbacks<PlanCacheKey, - SolutionCacheData, - mongo::plan_cache_debug_info::DebugInfo> - callbacks{*cq}; + auto decision = createDecision(1U); + auto callbacks = createCallback(*cq, *decision); // Verify that the plan cache size increases after adding new entry to cache. previousSize = planCacheTotalSizeEstimateBytes.get(); - ASSERT_OK(planCache.set(key, - qs->cacheData->clone(), - *decision, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decisionPtr)), - boost::none /* worksGrowthCoefficient */, - &callbacks)); + ASSERT_OK(planCache.set(key, qs->cacheData->clone(), *decision, Date_t{}, &callbacks)); ASSERT_GT(planCacheTotalSizeEstimateBytes.get(), previousSize); - decisionPtr = createDecision(1U); - decision = decisionPtr.get(); + decision = createDecision(1U); + auto callbacks1 = createCallback(*cq, *decision); // Verify that trying to set the same entry won't change the plan cache size. previousSize = planCacheTotalSizeEstimateBytes.get(); - ASSERT_OK(planCache.set(key, - qs->cacheData->clone(), - *decision, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decisionPtr)), - boost::none /* worksGrowthCoefficient */, - &callbacks)); + ASSERT_OK(planCache.set(key, qs->cacheData->clone(), *decision, Date_t{}, &callbacks1)); ASSERT_EQ(planCacheTotalSizeEstimateBytes.get(), previousSize); - decisionPtr = createDecision(2U); - decision = decisionPtr.get(); + decision = createDecision(2U); + auto callbacks2 = createCallback(*cq, *decision); // Verify that the plan cache size increases after updating the same entry with more solutions. - ASSERT_OK(planCache.set(key, - qs->cacheData->clone(), - *decision, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decisionPtr)), - boost::none /* worksGrowthCoefficient */, - &callbacks)); + ASSERT_OK(planCache.set(key, qs->cacheData->clone(), *decision, Date_t{}, &callbacks2)); ASSERT_GT(planCacheTotalSizeEstimateBytes.get(), previousSize); - decisionPtr = createDecision(1U); - decision = decisionPtr.get(); + decision = createDecision(1U); + auto callbacks3 = createCallback(*cq, *decision); // Verify that the plan cache size decreases after updating the same entry with fewer solutions. previousSize = planCacheTotalSizeEstimateBytes.get(); - ASSERT_OK(planCache.set(key, - qs->cacheData->clone(), - *decision, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decisionPtr)), - boost::none /* worksGrowthCoefficient */, - &callbacks)); + ASSERT_OK(planCache.set(key, qs->cacheData->clone(), *decision, Date_t{}, &callbacks3)); ASSERT_LT(planCacheTotalSizeEstimateBytes.get(), previousSize); ASSERT_GT(planCacheTotalSizeEstimateBytes.get(), originalSize); @@ -1857,19 +1751,14 @@ TEST(PlanCacheTest, PlanCacheSizeWithCRUDOperations) { long long sizeWithOneEntry = planCacheTotalSizeEstimateBytes.get(); std::string queryString = "{a: 1, c: 1}"; for (int i = 0; i < 5; ++i) { - decisionPtr = createDecision(1U); - decision = decisionPtr.get(); // Update the field name in the query string so that plan cache creates a new entry. queryString[1] = 'b' + i; unique_ptr<CanonicalQuery> query(canonicalize(queryString)); + decision = createDecision(1U); + auto callbacks4 = createCallback(*query, *decision); previousSize = planCacheTotalSizeEstimateBytes.get(); - ASSERT_OK(planCache.set(makeKey(*query), - qs->cacheData->clone(), - *decision, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decisionPtr)), - boost::none /* worksGrowthCoefficient */, - &callbacks)); + ASSERT_OK(planCache.set( + makeKey(*query), qs->cacheData->clone(), *decision, Date_t{}, &callbacks4)); ASSERT_GT(planCacheTotalSizeEstimateBytes.get(), previousSize); } @@ -1909,45 +1798,26 @@ TEST(PlanCacheTest, PlanCacheSizeWithEviction) { // Add entries until plan cache is full and verify that the size keeps increasing. std::string queryString = "{a: 1, c: 1}"; for (size_t i = 0; i < kCacheSize; ++i) { - auto decisionPtr = createDecision(2U); - auto decision = decisionPtr.get(); // Update the field name in the query string so that plan cache creates a new entry. queryString[1]++; unique_ptr<CanonicalQuery> query(canonicalize(queryString)); previousSize = planCacheTotalSizeEstimateBytes.get(); - PlanCacheLoggingCallbacks<PlanCacheKey, - SolutionCacheData, - mongo::plan_cache_debug_info::DebugInfo> - callbacks{*cq}; - ASSERT_OK(planCache.set(makeKey(*query), - qs->cacheData->clone(), - *decision, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decisionPtr)), - boost::none /* worksGrowthCoefficient */, - &callbacks)); + auto decision = createDecision(2U); + auto callbacks = createCallback(*query, *decision); + ASSERT_OK(planCache.set( + makeKey(*query), qs->cacheData->clone(), *decision, Date_t{}, &callbacks)); ASSERT_GT(planCacheTotalSizeEstimateBytes.get(), previousSize); } // Verify that adding entry of same size as evicted entry wouldn't change the plan cache size. { - auto decisionPtr = createDecision(2U); - auto decision = decisionPtr.get(); queryString = "{k: 1, c: 1}"; cq = unique_ptr<CanonicalQuery>(canonicalize(queryString)); - PlanCacheLoggingCallbacks<PlanCacheKey, - SolutionCacheData, - mongo::plan_cache_debug_info::DebugInfo> - callbacks{*cq}; + auto decision = createDecision(2U); + auto callbacks = createCallback(*cq, *decision); previousSize = planCacheTotalSizeEstimateBytes.get(); ASSERT_EQ(planCache.size(), kCacheSize); - ASSERT_OK(planCache.set(key, - qs->cacheData->clone(), - *decision, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decisionPtr)), - boost::none /* worksGrowthCoefficient */, - &callbacks)); + ASSERT_OK(planCache.set(key, qs->cacheData->clone(), *decision, Date_t{}, &callbacks)); ASSERT_EQ(planCache.size(), kCacheSize); ASSERT_EQ(planCacheTotalSizeEstimateBytes.get(), previousSize); } @@ -1955,67 +1825,37 @@ TEST(PlanCacheTest, PlanCacheSizeWithEviction) { // Verify that adding entry with query bigger than the evicted entry's key should change the // plan cache size. { - auto decisionPtr = createDecision(2U); - auto decision = decisionPtr.get(); queryString = "{k: 1, c: 1, extraField: 1}"; unique_ptr<CanonicalQuery> queryBiggerKey(canonicalize(queryString)); - PlanCacheLoggingCallbacks<PlanCacheKey, - SolutionCacheData, - mongo::plan_cache_debug_info::DebugInfo> - callbacks{*queryBiggerKey}; + auto decision = createDecision(2U); + auto callbacks = createCallback(*queryBiggerKey, *decision); previousSize = planCacheTotalSizeEstimateBytes.get(); - ASSERT_OK( - planCache.set(makeKey(*queryBiggerKey), - qs->cacheData->clone(), - *decision, - Date_t{}, - plan_cache_util::buildDebugInfo(*queryBiggerKey, std::move(decisionPtr)), - boost::none /* worksGrowthCoefficient */, - &callbacks)); + ASSERT_OK(planCache.set( + makeKey(*queryBiggerKey), qs->cacheData->clone(), *decision, Date_t{}, &callbacks)); ASSERT_GT(planCacheTotalSizeEstimateBytes.get(), previousSize); } // Verify that adding entry with query solutions larger than the evicted entry's query solutions // should increase the plan cache size. { - auto decisionPtr = createDecision(3U); - auto decision = decisionPtr.get(); queryString = "{l: 1, c: 1}"; cq = unique_ptr<CanonicalQuery>(canonicalize(queryString)); - PlanCacheLoggingCallbacks<PlanCacheKey, - SolutionCacheData, - mongo::plan_cache_debug_info::DebugInfo> - callbacks{*cq}; + auto decision = createDecision(3U); + auto callbacks = createCallback(*cq, *decision); previousSize = planCacheTotalSizeEstimateBytes.get(); - ASSERT_OK(planCache.set(key, - qs->cacheData->clone(), - *decision, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decisionPtr)), - boost::none /* worksGrowthCoefficient */, - &callbacks)); + ASSERT_OK(planCache.set(key, qs->cacheData->clone(), *decision, Date_t{}, &callbacks)); ASSERT_GT(planCacheTotalSizeEstimateBytes.get(), previousSize); } // Verify that adding entry with query solutions smaller than the evicted entry's query // solutions should decrease the plan cache size. { - auto decisionPtr = createDecision(1U); - auto decision = decisionPtr.get(); queryString = "{m: 1, c: 1}"; cq = unique_ptr<CanonicalQuery>(canonicalize(queryString)); - PlanCacheLoggingCallbacks<PlanCacheKey, - SolutionCacheData, - mongo::plan_cache_debug_info::DebugInfo> - callbacks{*cq}; + auto decision = createDecision(1U); + auto callbacks = createCallback(*cq, *decision); previousSize = planCacheTotalSizeEstimateBytes.get(); - ASSERT_OK(planCache.set(key, - qs->cacheData->clone(), - *decision, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decisionPtr)), - boost::none /* worksGrowthCoefficient */, - &callbacks)); + ASSERT_OK(planCache.set(key, qs->cacheData->clone(), *decision, Date_t{}, &callbacks)); ASSERT_LT(planCacheTotalSizeEstimateBytes.get(), previousSize); // clear() should reset the size. @@ -2034,27 +1874,21 @@ TEST(PlanCacheTest, PlanCacheSizeWithMultiplePlanCaches) { // Verify that adding entries to both plan caches will keep increasing the cache size. std::string queryString = "{a: 1, c: 1}"; for (int i = 0; i < 5; ++i) { - auto decision = createDecision(1U); - auto decisionPtr = decision.get(); // Update the field name in the query string so that plan cache creates a new entry. queryString[1] = 'b' + i; unique_ptr<CanonicalQuery> query(canonicalize(queryString)); + auto decision = createDecision(1U); + auto callbacks = createCallback(*query, *decision); previousSize = planCacheTotalSizeEstimateBytes.get(); - ASSERT_OK(planCache1.set(makeKey(*query), - qs->cacheData->clone(), - *decisionPtr, - Date_t{}, - plan_cache_util::buildDebugInfo(*query, std::move(decision)))); + ASSERT_OK(planCache1.set( + makeKey(*query), qs->cacheData->clone(), *decision, Date_t{}, &callbacks)); ASSERT_GT(planCacheTotalSizeEstimateBytes.get(), previousSize); decision = createDecision(1U); - decisionPtr = decision.get(); + auto callbacks1 = createCallback(*query, *decision); previousSize = planCacheTotalSizeEstimateBytes.get(); - ASSERT_OK(planCache2.set(makeKey(*query), - qs->cacheData->clone(), - *decisionPtr, - Date_t{}, - plan_cache_util::buildDebugInfo(*query, std::move(decision)))); + ASSERT_OK(planCache2.set( + makeKey(*query), qs->cacheData->clone(), *decision, Date_t{}, &callbacks1)); ASSERT_GT(planCacheTotalSizeEstimateBytes.get(), previousSize); } @@ -2072,14 +1906,11 @@ TEST(PlanCacheTest, PlanCacheSizeWithMultiplePlanCaches) { long long sizeBeforeScopedPlanCache = planCacheTotalSizeEstimateBytes.get(); { auto decision = createDecision(1U); - auto decisionPtr = decision.get(); + auto callbacks = createCallback(*cq, *decision); PlanCache planCache(5000); previousSize = planCacheTotalSizeEstimateBytes.get(); - ASSERT_OK(planCache.set(makeKey(*cq), - qs->cacheData->clone(), - *decisionPtr, - Date_t{}, - plan_cache_util::buildDebugInfo(*cq, std::move(decision)))); + ASSERT_OK( + planCache.set(makeKey(*cq), qs->cacheData->clone(), *decision, Date_t{}, &callbacks)); ASSERT_GT(planCacheTotalSizeEstimateBytes.get(), previousSize); } @@ -2101,13 +1932,10 @@ TEST(PlanCacheTest, PlanCacheMaxSizeParameterCanBeZero) { unique_ptr<CanonicalQuery> query(canonicalize("{a: 1, c: 1}")); auto qs = getQuerySolutionForCaching(); auto decision = createDecision(1U); - auto decisionPtr = decision.get(); + auto callbacks = createCallback(*query, *decision); - ASSERT_OK(planCache.set(makeKey(*query), - qs->cacheData->clone(), - *decisionPtr, - Date_t{}, - plan_cache_util::buildDebugInfo(*query, std::move(decision)))); + ASSERT_OK( + planCache.set(makeKey(*query), qs->cacheData->clone(), *decision, Date_t{}, &callbacks)); ASSERT_EQ(0U, planCache.size()); } } // namespace |