SERVER-112429 Make SBE hash lookup tests more efficient (#42602) (#42618)

GitOrigin-RevId: ed7c93f98afa2a5088083f0c49cd79f2d1d4ec3f
This commit is contained in:
Jan 2025-10-22 20:48:52 +02:00 committed by MongoDB Bot
parent f53ae515e8
commit 3585bbee40
6 changed files with 42 additions and 53 deletions

View File

@ -44,17 +44,15 @@ void HashLookupSharedTest::prepareAndEvalStageWithReopen(
// Execute the stage normally.
std::stringstream firstStream;
StageResultsPrinters::make(firstStream, printOptions).printStageResults(ctx, slotNames, stage);
std::string firstStr = firstStream.str();
stream << "--- First Stats" << std::endl;
stream << "--- First Stats\n";
printHashLookupStats(stream, stage);
// Execute the stage after reopen and verify that output is the same.
stage->open(true);
std::stringstream secondStream;
StageResultsPrinters::make(secondStream, printOptions).printStageResults(ctx, slotNames, stage);
std::string secondStr = secondStream.str();
ASSERT_EQ(firstStr, secondStr);
stream << "--- Second Stats" << std::endl;
ASSERT_EQ(firstStream.view(), secondStream.view());
stream << "--- Second Stats\n";
printHashLookupStats(stream, stage);
// Execute the stage after close and open and verify that output is the same.
@ -62,9 +60,8 @@ void HashLookupSharedTest::prepareAndEvalStageWithReopen(
stage->open(false);
std::stringstream thirdStream;
StageResultsPrinters::make(thirdStream, printOptions).printStageResults(ctx, slotNames, stage);
std::string thirdStr = thirdStream.str();
ASSERT_EQ(firstStr, thirdStr);
stream << "--- Third Stats" << std::endl;
ASSERT_EQ(firstStream.view(), thirdStream.view());
stream << "--- Third Stats\n";
printHashLookupStats(stream, stage);
stage->close();
@ -84,37 +81,33 @@ void HashLookupSharedTest::prepareAndEvalStageWithReopen(
stage->open(true);
std::stringstream fourthStream;
StageResultsPrinters::make(fourthStream, printOptions).printStageResults(ctx, slotNames, stage);
std::string fourthStr = fourthStream.str();
ASSERT_EQ(firstStr, fourthStr);
stream << "--- Fourth Stats" << std::endl;
ASSERT_EQ(firstStream.view(), fourthStream.view());
stream << "--- Fourth Stats\n";
printHashLookupStats(stream, stage);
stream << std::endl;
stream << '\n';
// Execute the stage after close and open and verify that output is the same.
stage->close();
stage->open(false);
std::stringstream fifthStream;
StageResultsPrinters::make(fifthStream, printOptions).printStageResults(ctx, slotNames, stage);
std::string fifthStr = fifthStream.str();
ASSERT_EQ(firstStr, fifthStr);
stream << "--- Fifth Stats" << std::endl;
ASSERT_EQ(firstStream.view(), fifthStream.view());
stream << "--- Fifth Stats\n";
printHashLookupStats(stream, stage);
stream << std::endl;
stream << '\n';
// Execute the stage after reopen and we have spilled to disk and verify that output is the
// same.
stage->open(true);
std::stringstream sixthStream;
StageResultsPrinters::make(sixthStream, printOptions).printStageResults(ctx, slotNames, stage);
std::string sixthStr = sixthStream.str();
ASSERT_EQ(firstStr, sixthStr);
stream << "--- Sixth Stats" << std::endl;
ASSERT_EQ(firstStream.view(), sixthStream.view());
stream << "--- Sixth Stats\n";
printHashLookupStats(stream, stage);
stream << std::endl;
stream << '\n';
stage->close();
stream << "-- OUTPUT ";
stream << firstStr;
stream << "-- OUTPUT " << firstStream.view();
} // prepareAndEvalStageWithReopen
} // namespace mongo::sbe

View File

@ -115,11 +115,11 @@ protected:
printHashLookupStats(stream, stats);
}
static void printHashLookupStats(std::ostream& stream, const HashLookupStats* stats) {
stream << "dsk:" << stats->usedDisk << std::endl;
stream << "htRecs:" << stats->spillingHtStats.getSpilledRecords() << std::endl;
stream << "htIndices:" << stats->spillingHtStats.getSpilledBytes() << std::endl;
stream << "buffRecs:" << stats->spillingBuffStats.getSpilledRecords() << std::endl;
stream << "buffBytes:" << stats->spillingBuffStats.getSpilledBytes() << std::endl;
stream << "dsk:" << stats->usedDisk << '\n';
stream << "htRecs:" << stats->spillingHtStats.getSpilledRecords() << '\n';
stream << "htIndices:" << stats->spillingHtStats.getSpilledBytes() << '\n';
stream << "buffRecs:" << stats->spillingBuffStats.getSpilledRecords() << '\n';
stream << "buffBytes:" << stats->spillingBuffStats.getSpilledBytes() << '\n';
}
};
} // namespace mongo::sbe

View File

@ -46,16 +46,16 @@ public:
CollatorInterface* collator = nullptr) override {
auto& stream = gctx.outStream();
if (stream.tellp()) {
stream << std::endl;
stream << '\n';
}
stream << "==== VARIATION: " << name << " ====" << std::endl;
stream << "==== VARIATION: " << name << " ====\n";
if (collator) {
stream << "COLLATOR: ";
value::ValuePrinters::make(stream, printOptions).writeCollatorToStream(collator);
stream << std::endl;
stream << '\n';
}
stream << "-- INPUTS:" << std::endl;
stream << "-- INPUTS:\n";
// Build a scan for the outer loop.
auto [outerScanSlots, outerScanStage] = generateVirtualScanMulti(2, outer);
@ -63,7 +63,7 @@ public:
cloneAndEvalStage(stream,
{{outerScanSlots[0], "value"}, {outerScanSlots[1], "key"}},
outerScanStage.get());
stream << std::endl;
stream << '\n';
// Build a scan for the inner loop.
auto [innerScanSlots, innerScanStage] = generateVirtualScanMulti(2, inner);
@ -71,7 +71,7 @@ public:
cloneAndEvalStage(stream,
{{innerScanSlots[0], "value"}, {innerScanSlots[1], "key"}},
innerScanStage.get());
stream << std::endl;
stream << '\n';
// Prepare and eval stage
auto ctx = makeCompileCtx();
@ -101,6 +101,7 @@ public:
kEmptyPlanNodeId);
StageResultsPrinters::SlotNames slotNames;
slotNames.reserve(2);
if (outerKeyOnly) {
slotNames.emplace_back(outerScanSlots[1], "outer_key");
} else {
@ -317,6 +318,7 @@ TEST_F(HashLookupStageTest, ForceSpillTest) {
kEmptyPlanNodeId);
value::SlotVector lookupSlots;
lookupSlots.reserve(2);
lookupSlots.push_back(outerScanSlots[0]);
lookupSlots.push_back(lookupStageOutputSlot);
auto resultAccessors = prepareTree(ctx.get(), lookupStage.get(), lookupSlots);
@ -325,6 +327,7 @@ TEST_F(HashLookupStageTest, ForceSpillTest) {
std::vector<std::pair<value::TypeTags, value::Value>> flatValues;
while (lookupStage->getNext() == PlanState::ADVANCED) {
std::vector<std::pair<value::TypeTags, value::Value>> results{};
results.reserve(resultAccessors.size());
for (size_t i = 0; i < resultAccessors.size(); ++i) {
flatValues.emplace_back(resultAccessors[i]->getCopyOfValue());
results.emplace_back(flatValues.back());

View File

@ -34,7 +34,6 @@
#include "mongo/db/exec/sbe/sbe_hash_lookup_shared_test.h"
#include "mongo/db/exec/sbe/stages/hash_lookup_unwind.h"
namespace mongo::sbe {
class HashLookupUnwindStageTest : public HashLookupSharedTest {
@ -47,16 +46,16 @@ public:
CollatorInterface* collator = nullptr) override {
auto& stream = gctx.outStream();
if (stream.tellp()) {
stream << std::endl;
stream << '\n';
}
stream << "==== VARIATION: " << name << " ====" << std::endl;
stream << "==== VARIATION: " << name << " ====\n";
if (collator) {
stream << "COLLATOR: ";
value::ValuePrinters::make(stream, printOptions).writeCollatorToStream(collator);
stream << std::endl;
stream << '\n';
}
stream << "-- INPUTS:" << std::endl;
stream << "-- INPUTS:\n";
// Build a scan for the outer loop.
auto [outerScanSlots, outerScanStage] = generateVirtualScanMulti(2, outer);
@ -64,7 +63,7 @@ public:
cloneAndEvalStage(stream,
{{outerScanSlots[0], "value"}, {outerScanSlots[1], "key"}},
outerScanStage.get());
stream << std::endl;
stream << '\n';
// Build a scan for the inner loop.
auto [innerScanSlots, innerScanStage] = generateVirtualScanMulti(2, inner);
@ -72,7 +71,7 @@ public:
cloneAndEvalStage(stream,
{{innerScanSlots[0], "value"}, {innerScanSlots[1], "key"}},
innerScanStage.get());
stream << std::endl;
stream << '\n';
// Prepare and eval stage
auto ctx = makeCompileCtx();
@ -100,6 +99,7 @@ public:
kEmptyPlanNodeId);
StageResultsPrinters::SlotNames slotNames;
slotNames.reserve(2);
if (outerKeyOnly) {
slotNames.emplace_back(outerScanSlots[1], "outer_key");
} else {
@ -308,6 +308,7 @@ TEST_F(HashLookupUnwindStageTest, ForceSpillTest) {
kEmptyPlanNodeId);
value::SlotVector lookupSlots;
lookupSlots.reserve(2);
lookupSlots.push_back(outerScanSlots[0]);
lookupSlots.push_back(lookupStageOutputSlot);
auto resultAccessors = prepareTree(ctx.get(), lookupStage.get(), lookupSlots);
@ -317,6 +318,7 @@ TEST_F(HashLookupUnwindStageTest, ForceSpillTest) {
std::vector<std::pair<value::TypeTags, value::Value>> flatValues;
while (lookupStage->getNext() == PlanState::ADVANCED) {
std::vector<std::pair<value::TypeTags, value::Value>> results{};
results.reserve(resultAccessors.size());
for (size_t i = 0; i < resultAccessors.size(); ++i) {
flatValues.emplace_back(resultAccessors[i]->getCopyOfValue());
results.emplace_back(flatValues.back());

View File

@ -36,8 +36,6 @@
#include <cstddef>
#include <absl/container/inlined_vector.h>
namespace mongo::sbe {
template <typename T>
@ -53,6 +51,7 @@ void StageResultsPrinter<T>::printStageResults(CompileCtx* ctx,
PlanStage* stage) {
tassert(6441701, "slots and names sizes must match", slots.size() == names.size());
SlotNames slotNames;
slotNames.reserve(slots.size());
size_t idx = 0;
for (auto slot : slots) {
slotNames.emplace_back(slot, names[idx++]);
@ -66,19 +65,18 @@ void StageResultsPrinter<T>::printStageResults(CompileCtx* ctx,
const SlotNames& slotNames,
PlanStage* stage) {
std::vector<value::SlotAccessor*> accessors;
accessors.reserve(slotNames.size());
for (const auto& slot : slotNames) {
accessors.push_back(stage->getAccessor(*ctx, slot.first));
}
printSlotNames(slotNames);
_stream << ":"
<< "\n";
_stream << ":\n";
size_t iter = 0;
for (auto st = stage->getNext(); st == PlanState::ADVANCED; st = stage->getNext(), iter++) {
if (iter >= _options.arrayObjectOrNestingMaxDepth()) {
_stream << "..."
<< "\n";
_stream << "...\n";
break;
}

View File

@ -32,22 +32,15 @@
#include "mongo/bson/oid.h"
#include "mongo/bson/timestamp.h"
#include "mongo/db/basic_types_gen.h"
#include "mongo/db/exec/sbe/makeobj_spec.h"
#include "mongo/db/exec/sbe/sort_spec.h"
#include "mongo/db/exec/sbe/values/block_interface.h"
#include "mongo/db/exec/sbe/values/cell_interface.h"
#include "mongo/db/exec/sbe/values/value.h"
#include "mongo/db/fts/fts_matcher.h"
#include "mongo/db/fts/fts_query_impl.h"
#include "mongo/db/query/compiler/physical_model/index_bounds/index_bounds.h"
#include "mongo/db/query/datetime/date_time_support.h"
#include "mongo/db/record_id.h"
#include "mongo/db/storage/key_string/key_string.h"
#include "mongo/platform/decimal128.h"
#include "mongo/util/assert_util.h"
#include "mongo/util/hex.h"
#include "mongo/util/pcre.h"
#include "mongo/util/pcre_util.h"
#include <algorithm>
#include <cstdint>