summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorAnton Korshunov <anton.korshunov@mongodb.com>2021-01-28 15:52:50 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-02-05 07:21:33 +0000
commit8fbc7b1b11a15625bc1025d2e30decb5ca2e48b3 (patch)
treebb0fdfba643c67e44592b68e62f6a7612750c49a /src/mongo
parent2e376c871e15844736b285b8f68d003a7cf889d0 (diff)
downloadmongo-8fbc7b1b11a15625bc1025d2e30decb5ca2e48b3.tar.gz
SERVER-53271 Compute executionTimeMillisEstimates metric for SBE PlanStages
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/exec/sbe/stages/branch.cpp6
-rw-r--r--src/mongo/db/exec/sbe/stages/bson_scan.cpp6
-rw-r--r--src/mongo/db/exec/sbe/stages/check_bounds.cpp8
-rw-r--r--src/mongo/db/exec/sbe/stages/co_scan.cpp6
-rw-r--r--src/mongo/db/exec/sbe/stages/exchange.cpp12
-rw-r--r--src/mongo/db/exec/sbe/stages/filter.h6
-rw-r--r--src/mongo/db/exec/sbe/stages/hash_agg.cpp6
-rw-r--r--src/mongo/db/exec/sbe/stages/hash_join.cpp6
-rw-r--r--src/mongo/db/exec/sbe/stages/ix_scan.cpp8
-rw-r--r--src/mongo/db/exec/sbe/stages/limit_skip.cpp6
-rw-r--r--src/mongo/db/exec/sbe/stages/loop_join.cpp6
-rw-r--r--src/mongo/db/exec/sbe/stages/makeobj.cpp6
-rw-r--r--src/mongo/db/exec/sbe/stages/project.cpp6
-rw-r--r--src/mongo/db/exec/sbe/stages/scan.cpp12
-rw-r--r--src/mongo/db/exec/sbe/stages/sort.cpp6
-rw-r--r--src/mongo/db/exec/sbe/stages/spool.cpp12
-rw-r--r--src/mongo/db/exec/sbe/stages/spool.h6
-rw-r--r--src/mongo/db/exec/sbe/stages/stages.h27
-rw-r--r--src/mongo/db/exec/sbe/stages/text_match.cpp6
-rw-r--r--src/mongo/db/exec/sbe/stages/traverse.cpp6
-rw-r--r--src/mongo/db/exec/sbe/stages/union.cpp6
-rw-r--r--src/mongo/db/exec/sbe/stages/unique.cpp6
-rw-r--r--src/mongo/db/exec/sbe/stages/unwind.cpp6
-rw-r--r--src/mongo/db/query/stage_builder_util.cpp6
24 files changed, 187 insertions, 0 deletions
diff --git a/src/mongo/db/exec/sbe/stages/branch.cpp b/src/mongo/db/exec/sbe/stages/branch.cpp
index 15db672a013..36715084bd9 100644
--- a/src/mongo/db/exec/sbe/stages/branch.cpp
+++ b/src/mongo/db/exec/sbe/stages/branch.cpp
@@ -106,6 +106,8 @@ value::SlotAccessor* BranchStage::getAccessor(CompileCtx& ctx, value::SlotId slo
}
void BranchStage::open(bool reOpen) {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.opens++;
_specificStats.numTested++;
@@ -132,6 +134,8 @@ void BranchStage::open(bool reOpen) {
}
PlanState BranchStage::getNext() {
+ auto optTimer(getOptTimer(_opCtx));
+
if (!_activeBranch) {
return trackPlanState(PlanState::IS_EOF);
}
@@ -158,6 +162,8 @@ PlanState BranchStage::getNext() {
}
void BranchStage::close() {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.closes++;
if (_thenOpened) {
diff --git a/src/mongo/db/exec/sbe/stages/bson_scan.cpp b/src/mongo/db/exec/sbe/stages/bson_scan.cpp
index 6de5c52b659..f3222d6c04a 100644
--- a/src/mongo/db/exec/sbe/stages/bson_scan.cpp
+++ b/src/mongo/db/exec/sbe/stages/bson_scan.cpp
@@ -82,11 +82,15 @@ value::SlotAccessor* BSONScanStage::getAccessor(CompileCtx& ctx, value::SlotId s
}
void BSONScanStage::open(bool reOpen) {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.opens++;
_bsonCurrent = _bsonBegin;
}
PlanState BSONScanStage::getNext() {
+ auto optTimer(getOptTimer(_opCtx));
+
if (_bsonCurrent < _bsonEnd) {
if (_recordAccessor) {
_recordAccessor->reset(value::TypeTags::bsonObject,
@@ -129,6 +133,8 @@ PlanState BSONScanStage::getNext() {
}
void BSONScanStage::close() {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.closes++;
}
diff --git a/src/mongo/db/exec/sbe/stages/check_bounds.cpp b/src/mongo/db/exec/sbe/stages/check_bounds.cpp
index 539b8e3ffeb..0b8738a95b5 100644
--- a/src/mongo/db/exec/sbe/stages/check_bounds.cpp
+++ b/src/mongo/db/exec/sbe/stages/check_bounds.cpp
@@ -68,12 +68,16 @@ value::SlotAccessor* CheckBoundsStage::getAccessor(CompileCtx& ctx, value::SlotI
}
void CheckBoundsStage::open(bool reOpen) {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.opens++;
_children[0]->open(reOpen);
_isEOF = false;
}
PlanState CheckBoundsStage::getNext() {
+ auto optTimer(getOptTimer(_opCtx));
+
if (_isEOF) {
return trackPlanState(PlanState::IS_EOF);
}
@@ -114,6 +118,8 @@ PlanState CheckBoundsStage::getNext() {
// passed behind the current interval and need to signal the parent stage that we're
// done and can only continue further once the stage is reopened.
_isEOF = true;
+
+ ++_specificStats.seeks;
break;
}
}
@@ -122,6 +128,8 @@ PlanState CheckBoundsStage::getNext() {
}
void CheckBoundsStage::close() {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.closes++;
_children[0]->close();
}
diff --git a/src/mongo/db/exec/sbe/stages/co_scan.cpp b/src/mongo/db/exec/sbe/stages/co_scan.cpp
index cfa539148ac..99caf7876de 100644
--- a/src/mongo/db/exec/sbe/stages/co_scan.cpp
+++ b/src/mongo/db/exec/sbe/stages/co_scan.cpp
@@ -45,10 +45,14 @@ value::SlotAccessor* CoScanStage::getAccessor(CompileCtx& ctx, value::SlotId slo
}
void CoScanStage::open(bool reOpen) {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.opens++;
}
PlanState CoScanStage::getNext() {
+ auto optTimer(getOptTimer(_opCtx));
+
checkForInterrupt(_opCtx);
// Run forever.
@@ -66,6 +70,8 @@ const SpecificStats* CoScanStage::getSpecificStats() const {
}
void CoScanStage::close() {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.closes++;
}
diff --git a/src/mongo/db/exec/sbe/stages/exchange.cpp b/src/mongo/db/exec/sbe/stages/exchange.cpp
index ed52a7ead43..b6e6602ce69 100644
--- a/src/mongo/db/exec/sbe/stages/exchange.cpp
+++ b/src/mongo/db/exec/sbe/stages/exchange.cpp
@@ -197,6 +197,8 @@ value::SlotAccessor* ExchangeConsumer::getAccessor(CompileCtx& ctx, value::SlotI
return ctx.getAccessor(slot);
}
void ExchangeConsumer::open(bool reOpen) {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.opens++;
if (reOpen) {
@@ -289,6 +291,8 @@ void ExchangeConsumer::open(bool reOpen) {
}
PlanState ExchangeConsumer::getNext() {
+ auto optTimer(getOptTimer(_opCtx));
+
if (_orderPreserving) {
// Build a heap and return min element.
uasserted(4822834, "ordere exchange not yet implemented");
@@ -321,6 +325,8 @@ PlanState ExchangeConsumer::getNext() {
return trackPlanState(PlanState::IS_EOF);
}
void ExchangeConsumer::close() {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.closes++;
{
@@ -490,6 +496,8 @@ value::SlotAccessor* ExchangeProducer::getAccessor(CompileCtx& ctx, value::SlotI
return _children[0]->getAccessor(ctx, slot);
}
void ExchangeProducer::open(bool reOpen) {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.opens++;
if (reOpen) {
uasserted(4822839, "exchange producer cannot be reopened");
@@ -513,6 +521,8 @@ bool ExchangeProducer::appendData(size_t consumerId) {
}
PlanState ExchangeProducer::getNext() {
+ auto optTimer(getOptTimer(_opCtx));
+
while (_children[0]->getNext() == PlanState::ADVANCED) {
// Push to the correct pipe.
switch (_state->policy()) {
@@ -554,6 +564,8 @@ PlanState ExchangeProducer::getNext() {
return trackPlanState(PlanState::IS_EOF);
}
void ExchangeProducer::close() {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.closes++;
_children[0]->close();
}
diff --git a/src/mongo/db/exec/sbe/stages/filter.h b/src/mongo/db/exec/sbe/stages/filter.h
index 4d14cd1f20d..66760acf2f5 100644
--- a/src/mongo/db/exec/sbe/stages/filter.h
+++ b/src/mongo/db/exec/sbe/stages/filter.h
@@ -70,6 +70,8 @@ public:
}
void open(bool reOpen) final {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.opens++;
if constexpr (IsConst) {
@@ -86,6 +88,8 @@ public:
}
PlanState getNext() final {
+ auto optTimer(getOptTimer(_opCtx));
+
// The constant filter evaluates the predicate in the open method.
if constexpr (IsConst) {
if (!_childOpened) {
@@ -118,6 +122,8 @@ public:
}
void close() final {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.closes++;
if (_childOpened) {
diff --git a/src/mongo/db/exec/sbe/stages/hash_agg.cpp b/src/mongo/db/exec/sbe/stages/hash_agg.cpp
index 4c4a5b4f132..2424ba019de 100644
--- a/src/mongo/db/exec/sbe/stages/hash_agg.cpp
+++ b/src/mongo/db/exec/sbe/stages/hash_agg.cpp
@@ -102,6 +102,8 @@ value::SlotAccessor* HashAggStage::getAccessor(CompileCtx& ctx, value::SlotId sl
}
void HashAggStage::open(bool reOpen) {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.opens++;
_children[0]->open(reOpen);
@@ -140,6 +142,8 @@ void HashAggStage::open(bool reOpen) {
}
PlanState HashAggStage::getNext() {
+ auto optTimer(getOptTimer(_opCtx));
+
if (_htIt == _ht.end()) {
_htIt = _ht.begin();
} else {
@@ -178,6 +182,8 @@ const SpecificStats* HashAggStage::getSpecificStats() const {
}
void HashAggStage::close() {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.closes++;
_ht.clear();
}
diff --git a/src/mongo/db/exec/sbe/stages/hash_join.cpp b/src/mongo/db/exec/sbe/stages/hash_join.cpp
index 8e5e167f743..e92bbebdab4 100644
--- a/src/mongo/db/exec/sbe/stages/hash_join.cpp
+++ b/src/mongo/db/exec/sbe/stages/hash_join.cpp
@@ -119,6 +119,8 @@ value::SlotAccessor* HashJoinStage::getAccessor(CompileCtx& ctx, value::SlotId s
}
void HashJoinStage::open(bool reOpen) {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.opens++;
_children[0]->open(reOpen);
// Insert the outer side into the hash table.
@@ -152,6 +154,8 @@ void HashJoinStage::open(bool reOpen) {
}
PlanState HashJoinStage::getNext() {
+ auto optTimer(getOptTimer(_opCtx));
+
if (_htIt != _htItEnd) {
++_htIt;
}
@@ -183,6 +187,8 @@ PlanState HashJoinStage::getNext() {
}
void HashJoinStage::close() {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.closes++;
_children[1]->close();
}
diff --git a/src/mongo/db/exec/sbe/stages/ix_scan.cpp b/src/mongo/db/exec/sbe/stages/ix_scan.cpp
index 7a5e376ec2f..51402dd7dd6 100644
--- a/src/mongo/db/exec/sbe/stages/ix_scan.cpp
+++ b/src/mongo/db/exec/sbe/stages/ix_scan.cpp
@@ -170,6 +170,8 @@ void IndexScanStage::doAttachToTrialRunTracker(TrialRunTracker* tracker) {
}
void IndexScanStage::open(bool reOpen) {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.opens++;
invariant(_opCtx);
@@ -238,6 +240,8 @@ void IndexScanStage::open(bool reOpen) {
// TODO SERVER-49385: When the 'prepare()' phase takes the collection lock, it will be
// possible to intialize '_ordering' there instead of here.
_ordering = entry->ordering();
+
+ ++_specificStats.seeks;
} else {
_cursor.reset();
}
@@ -247,6 +251,8 @@ void IndexScanStage::open(bool reOpen) {
}
PlanState IndexScanStage::getNext() {
+ auto optTimer(getOptTimer(_opCtx));
+
if (!_cursor) {
return trackPlanState(PlanState::IS_EOF);
}
@@ -306,6 +312,8 @@ PlanState IndexScanStage::getNext() {
}
void IndexScanStage::close() {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.closes++;
_cursor.reset();
diff --git a/src/mongo/db/exec/sbe/stages/limit_skip.cpp b/src/mongo/db/exec/sbe/stages/limit_skip.cpp
index 528c9cd5cc3..b09e3e17a9b 100644
--- a/src/mongo/db/exec/sbe/stages/limit_skip.cpp
+++ b/src/mongo/db/exec/sbe/stages/limit_skip.cpp
@@ -61,6 +61,8 @@ value::SlotAccessor* LimitSkipStage::getAccessor(CompileCtx& ctx, value::SlotId
}
void LimitSkipStage::open(bool reOpen) {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.opens++;
_isEOF = false;
_children[0]->open(reOpen);
@@ -73,6 +75,8 @@ void LimitSkipStage::open(bool reOpen) {
_current = 0;
}
PlanState LimitSkipStage::getNext() {
+ auto optTimer(getOptTimer(_opCtx));
+
if (_isEOF || (_limit && _current++ == *_limit)) {
return trackPlanState(PlanState::IS_EOF);
}
@@ -80,6 +84,8 @@ PlanState LimitSkipStage::getNext() {
return trackPlanState(_children[0]->getNext());
}
void LimitSkipStage::close() {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.closes++;
_children[0]->close();
}
diff --git a/src/mongo/db/exec/sbe/stages/loop_join.cpp b/src/mongo/db/exec/sbe/stages/loop_join.cpp
index b8a1b294bec..0205cd9e2f0 100644
--- a/src/mongo/db/exec/sbe/stages/loop_join.cpp
+++ b/src/mongo/db/exec/sbe/stages/loop_join.cpp
@@ -88,6 +88,8 @@ value::SlotAccessor* LoopJoinStage::getAccessor(CompileCtx& ctx, value::SlotId s
}
void LoopJoinStage::open(bool reOpen) {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.opens++;
_children[0]->open(reOpen);
_outerGetNext = true;
@@ -103,6 +105,8 @@ void LoopJoinStage::openInner() {
}
PlanState LoopJoinStage::getNext() {
+ auto optTimer(getOptTimer(_opCtx));
+
if (_outerGetNext) {
auto state = _children[0]->getNext();
if (state != PlanState::ADVANCED) {
@@ -143,6 +147,8 @@ PlanState LoopJoinStage::getNext() {
}
void LoopJoinStage::close() {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.closes++;
if (_reOpenInner) {
diff --git a/src/mongo/db/exec/sbe/stages/makeobj.cpp b/src/mongo/db/exec/sbe/stages/makeobj.cpp
index 330e4358951..7985a27e592 100644
--- a/src/mongo/db/exec/sbe/stages/makeobj.cpp
+++ b/src/mongo/db/exec/sbe/stages/makeobj.cpp
@@ -126,6 +126,8 @@ void MakeObjStageBase<O>::projectField(UniqueBSONObjBuilder* bob, size_t idx) {
template <MakeObjOutputType O>
void MakeObjStageBase<O>::open(bool reOpen) {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.opens++;
_children[0]->open(reOpen);
}
@@ -279,6 +281,8 @@ void MakeObjStageBase<MakeObjOutputType::bsonObject>::produceObject() {
template <MakeObjOutputType O>
PlanState MakeObjStageBase<O>::getNext() {
+ auto optTimer(getOptTimer(_opCtx));
+
auto state = _children[0]->getNext();
if (state == PlanState::ADVANCED) {
@@ -289,6 +293,8 @@ PlanState MakeObjStageBase<O>::getNext() {
template <MakeObjOutputType O>
void MakeObjStageBase<O>::close() {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.closes++;
_children[0]->close();
}
diff --git a/src/mongo/db/exec/sbe/stages/project.cpp b/src/mongo/db/exec/sbe/stages/project.cpp
index 10cf54e2b2e..3520ca4c603 100644
--- a/src/mongo/db/exec/sbe/stages/project.cpp
+++ b/src/mongo/db/exec/sbe/stages/project.cpp
@@ -69,11 +69,15 @@ value::SlotAccessor* ProjectStage::getAccessor(CompileCtx& ctx, value::SlotId sl
}
}
void ProjectStage::open(bool reOpen) {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.opens++;
_children[0]->open(reOpen);
}
PlanState ProjectStage::getNext() {
+ auto optTimer(getOptTimer(_opCtx));
+
auto state = _children[0]->getNext();
if (state == PlanState::ADVANCED) {
@@ -90,6 +94,8 @@ PlanState ProjectStage::getNext() {
}
void ProjectStage::close() {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.closes++;
_children[0]->close();
}
diff --git a/src/mongo/db/exec/sbe/stages/scan.cpp b/src/mongo/db/exec/sbe/stages/scan.cpp
index d03a591394c..8b3a1052d26 100644
--- a/src/mongo/db/exec/sbe/stages/scan.cpp
+++ b/src/mongo/db/exec/sbe/stages/scan.cpp
@@ -166,6 +166,8 @@ void ScanStage::doAttachToTrialRunTracker(TrialRunTracker* tracker) {
}
void ScanStage::open(bool reOpen) {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.opens++;
invariant(_opCtx);
if (!reOpen) {
@@ -209,6 +211,8 @@ void ScanStage::open(bool reOpen) {
}
PlanState ScanStage::getNext() {
+ auto optTimer(getOptTimer(_opCtx));
+
if (!_cursor) {
return trackPlanState(PlanState::IS_EOF);
}
@@ -271,6 +275,8 @@ PlanState ScanStage::getNext() {
}
void ScanStage::close() {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.closes++;
_cursor.reset();
_coll.reset();
@@ -463,6 +469,8 @@ void ParallelScanStage::doAttachToOperationContext(OperationContext* opCtx) {
}
void ParallelScanStage::open(bool reOpen) {
+ auto optTimer(getOptTimer(_opCtx));
+
invariant(_opCtx);
invariant(!reOpen, "parallel scan is not restartable");
@@ -524,6 +532,8 @@ boost::optional<Record> ParallelScanStage::nextRange() {
}
PlanState ParallelScanStage::getNext() {
+ auto optTimer(getOptTimer(_opCtx));
+
if (!_cursor) {
_commonStats.isEOF = true;
return PlanState::IS_EOF;
@@ -587,6 +597,8 @@ PlanState ParallelScanStage::getNext() {
}
void ParallelScanStage::close() {
+ auto optTimer(getOptTimer(_opCtx));
+
_cursor.reset();
_coll.reset();
_open = false;
diff --git a/src/mongo/db/exec/sbe/stages/sort.cpp b/src/mongo/db/exec/sbe/stages/sort.cpp
index 291e302d25c..7126dbea9fc 100644
--- a/src/mongo/db/exec/sbe/stages/sort.cpp
+++ b/src/mongo/db/exec/sbe/stages/sort.cpp
@@ -157,6 +157,8 @@ void SortStage::doAttachToTrialRunTracker(TrialRunTracker* tracker) {
}
void SortStage::open(bool reOpen) {
+ auto optTimer(getOptTimer(_opCtx));
+
invariant(_opCtx);
_commonStats.opens++;
_children[0]->open(reOpen);
@@ -208,6 +210,8 @@ void SortStage::open(bool reOpen) {
}
PlanState SortStage::getNext() {
+ auto optTimer(getOptTimer(_opCtx));
+
// When the sort spilled data to disk then read back the sorted runs.
if (_mergeIt && _mergeIt->more()) {
_mergeData = _mergeIt->next();
@@ -219,6 +223,8 @@ PlanState SortStage::getNext() {
}
void SortStage::close() {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.closes++;
_mergeIt.reset();
_sorter.reset();
diff --git a/src/mongo/db/exec/sbe/stages/spool.cpp b/src/mongo/db/exec/sbe/stages/spool.cpp
index a5bfae94cde..e0a51b28748 100644
--- a/src/mongo/db/exec/sbe/stages/spool.cpp
+++ b/src/mongo/db/exec/sbe/stages/spool.cpp
@@ -74,6 +74,8 @@ value::SlotAccessor* SpoolEagerProducerStage::getAccessor(CompileCtx& ctx, value
}
void SpoolEagerProducerStage::open(bool reOpen) {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.opens++;
_children[0]->open(reOpen);
@@ -98,6 +100,8 @@ void SpoolEagerProducerStage::open(bool reOpen) {
}
PlanState SpoolEagerProducerStage::getNext() {
+ auto optTimer(getOptTimer(_opCtx));
+
if (_bufferIt == _buffer->size()) {
_bufferIt = 0;
} else {
@@ -112,6 +116,8 @@ PlanState SpoolEagerProducerStage::getNext() {
}
void SpoolEagerProducerStage::close() {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.closes++;
}
@@ -208,6 +214,8 @@ value::SlotAccessor* SpoolLazyProducerStage::getAccessor(CompileCtx& ctx, value:
}
void SpoolLazyProducerStage::open(bool reOpen) {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.opens++;
_children[0]->open(reOpen);
@@ -217,6 +225,8 @@ void SpoolLazyProducerStage::open(bool reOpen) {
}
PlanState SpoolLazyProducerStage::getNext() {
+ auto optTimer(getOptTimer(_opCtx));
+
auto state = _children[0]->getNext();
if (state == PlanState::ADVANCED) {
@@ -253,6 +263,8 @@ PlanState SpoolLazyProducerStage::getNext() {
}
void SpoolLazyProducerStage::close() {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.closes++;
}
diff --git a/src/mongo/db/exec/sbe/stages/spool.h b/src/mongo/db/exec/sbe/stages/spool.h
index 10b34939c6f..995b10076a0 100644
--- a/src/mongo/db/exec/sbe/stages/spool.h
+++ b/src/mongo/db/exec/sbe/stages/spool.h
@@ -181,11 +181,15 @@ public:
}
void open(bool reOpen) {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.opens++;
_bufferIt = _buffer->size();
}
PlanState getNext() {
+ auto optTimer(getOptTimer(_opCtx));
+
if constexpr (IsStack) {
if (_bufferIt != _buffer->size()) {
_buffer->erase(_buffer->begin() + _bufferIt);
@@ -211,6 +215,8 @@ public:
}
void close() {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.closes++;
}
diff --git a/src/mongo/db/exec/sbe/stages/stages.h b/src/mongo/db/exec/sbe/stages/stages.h
index 3b2fb96ab2e..e2afedfdbec 100644
--- a/src/mongo/db/exec/sbe/stages/stages.h
+++ b/src/mongo/db/exec/sbe/stages/stages.h
@@ -233,6 +233,20 @@ public:
stage->doAttachToTrialRunTracker(tracker);
}
+ /**
+ * Force this stage to collect timing info during its execution. Must not be called after
+ * execution has started.
+ */
+ void markShouldCollectTimingInfo() {
+ invariant(!_commonStats.executionTimeMillis || *_commonStats.executionTimeMillis == 0);
+ _commonStats.executionTimeMillis.emplace(0);
+
+ auto stage = static_cast<T*>(this);
+ for (auto&& child : stage->_children) {
+ child->markShouldCollectTimingInfo();
+ }
+ }
+
protected:
PlanState trackPlanState(PlanState state) {
if (state == PlanState::IS_EOF) {
@@ -244,6 +258,19 @@ protected:
return state;
}
+ /**
+ * Returns an optional timer which is used to collect time spent executing the current stage.
+ * May return boost::none if it is not necessary to collect timing info.
+ */
+ boost::optional<ScopedTimer> getOptTimer(OperationContext* opCtx) {
+ if (_commonStats.executionTimeMillis && opCtx) {
+ return {{opCtx->getServiceContext()->getFastClockSource(),
+ _commonStats.executionTimeMillis.get_ptr()}};
+ }
+
+ return boost::none;
+ }
+
CommonStats _commonStats;
};
diff --git a/src/mongo/db/exec/sbe/stages/text_match.cpp b/src/mongo/db/exec/sbe/stages/text_match.cpp
index cd4096d202c..25c2e21c53d 100644
--- a/src/mongo/db/exec/sbe/stages/text_match.cpp
+++ b/src/mongo/db/exec/sbe/stages/text_match.cpp
@@ -59,11 +59,15 @@ value::SlotAccessor* TextMatchStage::getAccessor(CompileCtx& ctx, value::SlotId
}
void TextMatchStage::open(bool reOpen) {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.opens++;
_children[0]->open(reOpen);
}
PlanState TextMatchStage::getNext() {
+ auto optTimer(getOptTimer(_opCtx));
+
auto state = _children[0]->getNext();
if (state == PlanState::ADVANCED) {
@@ -87,6 +91,8 @@ PlanState TextMatchStage::getNext() {
}
void TextMatchStage::close() {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.closes++;
_children[0]->close();
}
diff --git a/src/mongo/db/exec/sbe/stages/traverse.cpp b/src/mongo/db/exec/sbe/stages/traverse.cpp
index 25fa70a0e70..0d87e043aa3 100644
--- a/src/mongo/db/exec/sbe/stages/traverse.cpp
+++ b/src/mongo/db/exec/sbe/stages/traverse.cpp
@@ -124,6 +124,8 @@ value::SlotAccessor* TraverseStage::getAccessor(CompileCtx& ctx, value::SlotId s
}
void TraverseStage::open(bool reOpen) {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.opens++;
_children[0]->open(reOpen);
// Do not open the inner child as we do not have values of correlated parameters yet.
@@ -140,6 +142,8 @@ void TraverseStage::openInner(value::TypeTags tag, value::Value val) {
}
PlanState TraverseStage::getNext() {
+ auto optTimer(getOptTimer(_opCtx));
+
auto state = _children[0]->getNext();
if (state != PlanState::ADVANCED) {
return trackPlanState(state);
@@ -250,6 +254,8 @@ bool TraverseStage::traverse(value::SlotAccessor* inFieldAccessor,
}
void TraverseStage::close() {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.closes++;
if (_reOpenInner) {
diff --git a/src/mongo/db/exec/sbe/stages/union.cpp b/src/mongo/db/exec/sbe/stages/union.cpp
index 12993254c44..b762b063ce3 100644
--- a/src/mongo/db/exec/sbe/stages/union.cpp
+++ b/src/mongo/db/exec/sbe/stages/union.cpp
@@ -94,6 +94,8 @@ value::SlotAccessor* UnionStage::getAccessor(CompileCtx& ctx, value::SlotId slot
}
void UnionStage::open(bool reOpen) {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.opens++;
if (reOpen) {
std::queue<UnionBranch> emptyQueue;
@@ -109,6 +111,8 @@ void UnionStage::open(bool reOpen) {
}
PlanState UnionStage::getNext() {
+ auto optTimer(getOptTimer(_opCtx));
+
auto state = PlanState::IS_EOF;
while (!_remainingBranchesToDrain.empty() && state != PlanState::ADVANCED) {
@@ -137,6 +141,8 @@ PlanState UnionStage::getNext() {
}
void UnionStage::close() {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.closes++;
_currentStage = nullptr;
while (!_remainingBranchesToDrain.empty()) {
diff --git a/src/mongo/db/exec/sbe/stages/unique.cpp b/src/mongo/db/exec/sbe/stages/unique.cpp
index ac39588d607..a03162ebc35 100644
--- a/src/mongo/db/exec/sbe/stages/unique.cpp
+++ b/src/mongo/db/exec/sbe/stages/unique.cpp
@@ -56,11 +56,15 @@ value::SlotAccessor* UniqueStage::getAccessor(CompileCtx& ctx, value::SlotId slo
}
void UniqueStage::open(bool reOpen) {
+ auto optTimer(getOptTimer(_opCtx));
+
++_commonStats.opens;
_children[0]->open(reOpen);
}
PlanState UniqueStage::getNext() {
+ auto optTimer(getOptTimer(_opCtx));
+
while (_children[0]->getNext() == PlanState::ADVANCED) {
value::MaterializedRow key{_inKeyAccessors.size()};
size_t idx = 0;
@@ -84,6 +88,8 @@ PlanState UniqueStage::getNext() {
}
void UniqueStage::close() {
+ auto optTimer(getOptTimer(_opCtx));
+
_children[0]->close();
}
diff --git a/src/mongo/db/exec/sbe/stages/unwind.cpp b/src/mongo/db/exec/sbe/stages/unwind.cpp
index e16397332c7..3616517942a 100644
--- a/src/mongo/db/exec/sbe/stages/unwind.cpp
+++ b/src/mongo/db/exec/sbe/stages/unwind.cpp
@@ -87,6 +87,8 @@ value::SlotAccessor* UnwindStage::getAccessor(CompileCtx& ctx, value::SlotId slo
}
void UnwindStage::open(bool reOpen) {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.opens++;
_children[0]->open(reOpen);
@@ -95,6 +97,8 @@ void UnwindStage::open(bool reOpen) {
}
PlanState UnwindStage::getNext() {
+ auto optTimer(getOptTimer(_opCtx));
+
if (!_inArray) {
do {
auto state = _children[0]->getNext();
@@ -151,6 +155,8 @@ PlanState UnwindStage::getNext() {
}
void UnwindStage::close() {
+ auto optTimer(getOptTimer(_opCtx));
+
_commonStats.closes++;
_children[0]->close();
}
diff --git a/src/mongo/db/query/stage_builder_util.cpp b/src/mongo/db/query/stage_builder_util.cpp
index c3af8b207a9..e9d92bbd6c2 100644
--- a/src/mongo/db/query/stage_builder_util.cpp
+++ b/src/mongo/db/query/stage_builder_util.cpp
@@ -78,6 +78,12 @@ buildSlotBasedExecutableTree(OperationContext* opCtx,
root->attachToOperationContext(opCtx);
+ auto expCtx = cq.getExpCtxRaw();
+ tassert(5327100, "No expression context", expCtx);
+ if (expCtx->explain || expCtx->mayDbProfile) {
+ root->markShouldCollectTimingInfo();
+ }
+
// Register this plan to yield according to the configured policy.
sbeYieldPolicy->registerPlan(root.get());