summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuoxin Xu <ruoxin.xu@mongodb.com>2022-03-15 16:07:38 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-03-15 17:29:38 +0000
commitc51987df9a8b60a98e9f91ff0328208df60427f8 (patch)
treeff075abdb2120bcb21b096cd5cb263a01c751c1f
parent63a4f1e011860e34b8a29b6171e3cbdd58f15c8d (diff)
downloadmongo-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.cpp12
-rw-r--r--src/mongo/db/exec/plan_cache_util.h32
-rw-r--r--src/mongo/db/query/plan_cache.h23
-rw-r--r--src/mongo/db/query/plan_cache_callbacks.h15
-rw-r--r--src/mongo/db/query/plan_cache_test.cpp400
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