diff options
author | Nikita Lapkov <nikita.lapkov@mongodb.com> | 2022-04-28 18:36:26 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-04-28 20:54:03 +0000 |
commit | a88230980fbeefa27f3b7cc07776650c6dfdb49f (patch) | |
tree | e6f180f7c52eb1a367b679a3d4f1bb0b52275633 | |
parent | f03a09fbe1c71b82be4bcdc79f8f0c6861f066c3 (diff) | |
download | mongo-a88230980fbeefa27f3b7cc07776650c6dfdb49f.tar.gz |
SERVER-65961 Copy only BSON types during yielding of SBE plans
-rw-r--r-- | src/mongo/db/exec/sbe/stages/check_bounds.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/exec/sbe/stages/ix_scan.cpp | 10 | ||||
-rw-r--r-- | src/mongo/db/exec/sbe/stages/loop_join.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/exec/sbe/stages/makeobj.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/exec/sbe/stages/merge_join.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/exec/sbe/stages/project.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/exec/sbe/stages/scan.cpp | 12 | ||||
-rw-r--r-- | src/mongo/db/exec/sbe/stages/spool.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/exec/sbe/stages/stages.h | 32 | ||||
-rw-r--r-- | src/mongo/db/exec/sbe/stages/traverse.cpp | 6 | ||||
-rw-r--r-- | src/mongo/db/exec/sbe/stages/unwind.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/exec/sbe/values/slot.h | 16 |
12 files changed, 66 insertions, 30 deletions
diff --git a/src/mongo/db/exec/sbe/stages/check_bounds.cpp b/src/mongo/db/exec/sbe/stages/check_bounds.cpp index 2555956ef98..483e9f50260 100644 --- a/src/mongo/db/exec/sbe/stages/check_bounds.cpp +++ b/src/mongo/db/exec/sbe/stages/check_bounds.cpp @@ -223,6 +223,6 @@ void CheckBoundsStage::doSaveState(bool relinquishCursor) { return; } - _outAccessor.makeOwned(); + prepareForYielding(_outAccessor); } } // namespace mongo::sbe diff --git a/src/mongo/db/exec/sbe/stages/ix_scan.cpp b/src/mongo/db/exec/sbe/stages/ix_scan.cpp index f16f2f6ee67..bfad6d9a2ae 100644 --- a/src/mongo/db/exec/sbe/stages/ix_scan.cpp +++ b/src/mongo/db/exec/sbe/stages/ix_scan.cpp @@ -159,13 +159,13 @@ void IndexScanStage::doSaveState(bool relinquishCursor) { if (relinquishCursor) { if (slotsAccessible()) { if (_recordAccessor) { - _recordAccessor->makeOwned(); + prepareForYielding(*_recordAccessor); } if (_recordIdAccessor) { - _recordIdAccessor->makeOwned(); + prepareForYielding(*_recordIdAccessor); } for (auto& accessor : _accessors) { - accessor.makeOwned(); + prepareForYielding(accessor); } } @@ -173,10 +173,10 @@ void IndexScanStage::doSaveState(bool relinquishCursor) { // as the index scan is opened. if (_open) { if (_seekKeyLowHolder) { - _seekKeyLowHolder->makeOwned(); + prepareForYielding(*_seekKeyLowHolder); } if (_seekKeyHighHolder) { - _seekKeyHighHolder->makeOwned(); + prepareForYielding(*_seekKeyHighHolder); } } diff --git a/src/mongo/db/exec/sbe/stages/loop_join.cpp b/src/mongo/db/exec/sbe/stages/loop_join.cpp index 78607a246f9..b319f94af11 100644 --- a/src/mongo/db/exec/sbe/stages/loop_join.cpp +++ b/src/mongo/db/exec/sbe/stages/loop_join.cpp @@ -165,8 +165,8 @@ void LoopJoinStage::close() { void LoopJoinStage::doSaveState(bool relinquishCursor) { if (_isReadingLeftSide || _outerGetNext) { - // If we yield while reading the left side, there is no need to makeOwned() data held in - // the right side, since we will have to re-open it anyway. + // If we yield while reading the left side, there is no need to prepareForYielding() data + // held in the right side, since we will have to re-open it anyway. const bool recursive = true; _children[1]->disableSlotAccess(recursive); } diff --git a/src/mongo/db/exec/sbe/stages/makeobj.cpp b/src/mongo/db/exec/sbe/stages/makeobj.cpp index e1c9cd6320e..e0402934517 100644 --- a/src/mongo/db/exec/sbe/stages/makeobj.cpp +++ b/src/mongo/db/exec/sbe/stages/makeobj.cpp @@ -424,7 +424,7 @@ void MakeObjStageBase<O>::doSaveState(bool relinquishCursor) { return; } - _obj.makeOwned(); + prepareForYielding(_obj); } // Explicit template instantiations. diff --git a/src/mongo/db/exec/sbe/stages/merge_join.cpp b/src/mongo/db/exec/sbe/stages/merge_join.cpp index dec5080fadf..170227e0575 100644 --- a/src/mongo/db/exec/sbe/stages/merge_join.cpp +++ b/src/mongo/db/exec/sbe/stages/merge_join.cpp @@ -328,8 +328,8 @@ void MergeJoinStage::doSaveState(bool relinquishCursor) { } // We only have to save shallow non-owning materialized rows. - _currentOuterKey.makeOwned(); - _currentInnerKey.makeOwned(); + prepareForYielding(_currentOuterKey); + prepareForYielding(_currentInnerKey); } std::unique_ptr<PlanStageStats> MergeJoinStage::getStats(bool includeDebugInfo) const { diff --git a/src/mongo/db/exec/sbe/stages/project.cpp b/src/mongo/db/exec/sbe/stages/project.cpp index bcc51d5b7b7..736110bc83a 100644 --- a/src/mongo/db/exec/sbe/stages/project.cpp +++ b/src/mongo/db/exec/sbe/stages/project.cpp @@ -161,7 +161,7 @@ void ProjectStage::doSaveState(bool relinquishCursor) { for (auto& [slotId, codeAndAccessor] : _fields) { auto& [code, accessor] = codeAndAccessor; - accessor.makeOwned(); + prepareForYielding(accessor); } } diff --git a/src/mongo/db/exec/sbe/stages/scan.cpp b/src/mongo/db/exec/sbe/stages/scan.cpp index cf1e40bf6cd..678d3f84ef9 100644 --- a/src/mongo/db/exec/sbe/stages/scan.cpp +++ b/src/mongo/db/exec/sbe/stages/scan.cpp @@ -183,13 +183,13 @@ void ScanStage::doSaveState(bool relinquishCursor) { if (relinquishCursor) { if (_recordAccessor) { - _recordAccessor->makeOwned(); + prepareForYielding(*_recordAccessor); } if (_recordIdAccessor) { - _recordIdAccessor->makeOwned(); + prepareForYielding(*_recordIdAccessor); } for (auto& [fieldName, accessor] : _fieldAccessors) { - accessor->makeOwned(); + prepareForYielding(*accessor); } } } @@ -722,13 +722,13 @@ void ParallelScanStage::doSaveState(bool relinquishCursor) { #endif if (_recordAccessor) { - _recordAccessor->makeOwned(); + prepareForYielding(*_recordAccessor); } if (_recordIdAccessor) { - _recordIdAccessor->makeOwned(); + prepareForYielding(*_recordIdAccessor); } for (auto& [fieldName, accessor] : _fieldAccessors) { - accessor->makeOwned(); + prepareForYielding(*accessor); } } diff --git a/src/mongo/db/exec/sbe/stages/spool.cpp b/src/mongo/db/exec/sbe/stages/spool.cpp index bf8a94e7c58..4550f569b09 100644 --- a/src/mongo/db/exec/sbe/stages/spool.cpp +++ b/src/mongo/db/exec/sbe/stages/spool.cpp @@ -279,7 +279,7 @@ void SpoolLazyProducerStage::doSaveState(bool relinquishCursor) { } for (auto& [slot, accessor] : _outAccessors) { - accessor.makeOwned(); + prepareForYielding(accessor); } } diff --git a/src/mongo/db/exec/sbe/stages/stages.h b/src/mongo/db/exec/sbe/stages/stages.h index e32aab56a84..59f6746a005 100644 --- a/src/mongo/db/exec/sbe/stages/stages.h +++ b/src/mongo/db/exec/sbe/stages/stages.h @@ -119,6 +119,26 @@ public: CanChangeState() = default; /** + * Ensures that accessor owns the underlying BSON value, which can be potentially owned by + * storage. + */ + static void prepareForYielding(value::OwnedValueAccessor& accessor) { + auto [tag, value] = accessor.getViewOfValue(); + if (shouldCopyValue(tag)) { + accessor.makeOwned(); + } + } + + static void prepareForYielding(value::MaterializedRow& row) { + for (size_t idx = 0; idx < row.size(); idx++) { + auto [tag, value] = row.getViewOfValue(idx); + if (shouldCopyValue(tag)) { + row.makeOwned(idx); + } + } + } + + /** * Notifies the stage that the underlying data source may change. * * It is illegal to call work() or isEOF() when a stage is in the "saved" state. May be called @@ -192,6 +212,18 @@ protected: enum class SaveState { kNotSaved, kSavedFull, kSavedNotFull }; SaveState _saveState{SaveState::kNotSaved}; #endif + + static bool shouldCopyValue(value::TypeTags tag) { + switch (tag) { + case value::TypeTags::Array: + case value::TypeTags::ArraySet: + case value::TypeTags::Object: + return false; + + default: + return true; + } + } }; template <typename T> diff --git a/src/mongo/db/exec/sbe/stages/traverse.cpp b/src/mongo/db/exec/sbe/stages/traverse.cpp index 7c117a0f7f9..d1e0a040b3e 100644 --- a/src/mongo/db/exec/sbe/stages/traverse.cpp +++ b/src/mongo/db/exec/sbe/stages/traverse.cpp @@ -278,8 +278,8 @@ void TraverseStage::close() { void TraverseStage::doSaveState(bool relinquishCursor) { if (_isReadingLeftSide) { - // If we yield while reading the left side, there is no need to makeOwned() data held in - // the right side, since we will have to re-open it anyway. + // If we yield while reading the left side, there is no need to prepareForYielding() data + // held in the right side, since we will have to re-open it anyway. const bool recursive = true; _children[1]->disableSlotAccess(recursive); @@ -292,7 +292,7 @@ void TraverseStage::doSaveState(bool relinquishCursor) { return; } - _outFieldOutputAccessor.makeOwned(); + prepareForYielding(_outFieldOutputAccessor); } void TraverseStage::doRestoreState(bool relinquishCursor) { diff --git a/src/mongo/db/exec/sbe/stages/unwind.cpp b/src/mongo/db/exec/sbe/stages/unwind.cpp index 41fe4be59c2..b4c5e225adc 100644 --- a/src/mongo/db/exec/sbe/stages/unwind.cpp +++ b/src/mongo/db/exec/sbe/stages/unwind.cpp @@ -207,10 +207,10 @@ void UnwindStage::doSaveState(bool fullSave) { } if (_outFieldOutputAccessor) { - _outFieldOutputAccessor->makeOwned(); + prepareForYielding(*_outFieldOutputAccessor); } if (_outIndexOutputAccessor) { - _outIndexOutputAccessor->makeOwned(); + prepareForYielding(*_outIndexOutputAccessor); } } diff --git a/src/mongo/db/exec/sbe/values/slot.h b/src/mongo/db/exec/sbe/values/slot.h index 1978ba1c959..f853f816d4d 100644 --- a/src/mongo/db/exec/sbe/values/slot.h +++ b/src/mongo/db/exec/sbe/values/slot.h @@ -402,12 +402,16 @@ public: */ void makeOwned() { for (size_t idx = 0; idx < _count; ++idx) { - if (!owned()[idx]) { - auto [tag, val] = value::copyValue(tags()[idx], values()[idx]); - values()[idx] = val; - tags()[idx] = tag; - owned()[idx] = true; - } + makeOwned(idx); + } + } + + void makeOwned(size_t idx) { + if (!owned()[idx]) { + auto [tag, val] = value::copyValue(tags()[idx], values()[idx]); + values()[idx] = val; + tags()[idx] = tag; + owned()[idx] = true; } } |