SERVER-108696 Move query stage memory limit knobs to a separate library and remove direct access (#39593)

GitOrigin-RevId: 1b7895170b77832a2947935e81420fe0f66c9e2a
This commit is contained in:
Ivan Fefer 2025-08-06 10:14:19 +02:00 committed by MongoDB Bot
parent 5dd73e5f5b
commit 99b45cf50d
41 changed files with 331 additions and 190 deletions

4
.github/CODEOWNERS vendored
View File

@ -2513,6 +2513,10 @@ WORKSPACE.bazel @10gen/devprod-build @svc-auto-approve-bot
/src/mongo/db/query/stage_builder/sbe/abt/**/* @10gen/query-execution-sbe @svc-auto-approve-bot
/src/mongo/db/query/stage_builder/sbe/abt/**/OWNERS.yml @10gen/query-execution-staff-leads @svc-auto-approve-bot
# The following patterns are parsed from ./src/mongo/db/query/stage_memory_limit_knobs/OWNERS.yml
/src/mongo/db/query/stage_memory_limit_knobs/**/* @10gen/query-execution @svc-auto-approve-bot
/src/mongo/db/query/stage_memory_limit_knobs/**/OWNERS.yml @10gen/query-execution-staff-leads @svc-auto-approve-bot
# The following patterns are parsed from ./src/mongo/db/query/timeseries/OWNERS.yml
/src/mongo/db/query/timeseries/**/* @10gen/query-integration-timeseries @svc-auto-approve-bot
/src/mongo/db/query/timeseries/**/OWNERS.yml @10gen/query-integration-staff-leads @svc-auto-approve-bot

View File

@ -1362,6 +1362,7 @@ mongo_cc_library(
"//src/mongo/db/query/plan_cache:query_plan_cache",
"//src/mongo/db/query/query_settings",
"//src/mongo/db/query/stage_builder/sbe:stage_builder",
"//src/mongo/db/query/stage_memory_limit_knobs",
"//src/mongo/db/query/write_ops:delete_request_idl",
"//src/mongo/db/query/write_ops:parsed_update",
"//src/mongo/db/query/write_ops:parsed_update_and_delete",
@ -2405,6 +2406,7 @@ mongo_cc_library(
"//src/mongo/db/exec:js_function",
"//src/mongo/db/query/collation:collator_interface", # TODO(SERVER-93876): Remove.
"//src/mongo/db/query/datetime:date_time_support", # TODO(SERVER-93876): Remove.
"//src/mongo/db/query/stage_memory_limit_knobs",
"//src/mongo/db/storage:storage_options", # TODO(SERVER-93876): Remove.
"//src/mongo/db/storage/key_string",
"//src/mongo/util:pcre_util",

View File

@ -738,7 +738,6 @@ mongo_cc_library(
"//src/mongo/db/query:query_knob_configuration.h",
"//src/mongo/db/query:query_knobs_gen",
"//src/mongo/db/query:query_request_helper.h",
"//src/mongo/db/query:query_stage_memory_limit_knobs_gen",
"//src/mongo/db/query:restore_context.h",
"//src/mongo/db/query:tailable_mode.h",
"//src/mongo/db/query:tailable_mode_gen",

View File

@ -33,7 +33,7 @@
#include "mongo/base/error_codes.h"
#include "mongo/db/memory_tracking/operation_memory_usage_tracker.h"
#include "mongo/db/query/query_knobs_gen.h"
#include "mongo/db/query/query_stage_memory_limit_knobs_gen.h"
#include "mongo/db/query/stage_memory_limit_knobs/knobs.h"
#include "mongo/db/record_id.h"
#include "mongo/db/sorter/sorter.h"
#include "mongo/db/sorter/sorter_file_name.h"
@ -69,7 +69,7 @@ SpoolStage::SpoolStage(ExpressionContext* expCtx, WorkingSet* ws, std::unique_pt
_memTracker(OperationMemoryUsageTracker::createMemoryUsageTrackerForStage(
*expCtx,
expCtx->getAllowDiskUse() && !expCtx->getInRouter(),
internalQueryMaxSpoolMemoryUsageBytes.load())) {
loadMemoryLimit(StageMemoryLimit::QueryMaxSpoolMemoryUsageBytes))) {
_specificStats.maxMemoryUsageBytes = _memTracker.maxAllowedMemoryUsageBytes();
_specificStats.maxDiskUsageBytes = internalQueryMaxSpoolDiskUsageBytes.load();
}

View File

@ -39,9 +39,9 @@
#include "mongo/db/namespace_string.h"
#include "mongo/db/pipeline/expression_context_builder.h"
#include "mongo/db/query/query_knobs_gen.h"
#include "mongo/db/query/query_stage_memory_limit_knobs_gen.h"
#include "mongo/db/service_context.h"
#include "mongo/db/service_context_d_test_fixture.h"
#include "mongo/idl/server_parameter_test_util.h"
#include "mongo/platform/atomic_word.h"
#include "mongo/stdx/type_traits.h"
#include "mongo/unittest/temp_dir.h"
@ -151,8 +151,10 @@ public:
expCtx()->setAllowDiskUse(maxAllowedDiskUsageBytes.has_value());
}
internalQueryMaxSpoolMemoryUsageBytes.store(maxAllowedMemoryUsageBytes);
internalQueryMaxSpoolDiskUsageBytes.store(maxAllowedDiskUsageBytes.value_or(0));
RAIIServerParameterControllerForTest maxMemoryUsage("internalQueryMaxSpoolMemoryUsageBytes",
maxAllowedMemoryUsageBytes);
RAIIServerParameterControllerForTest maxDiskUsage("internalQueryMaxSpoolDiskUsageBytes",
maxAllowedDiskUsageBytes.value_or(1));
return SpoolStage(expCtx(), &ws, std::move(root));
}
@ -389,7 +391,7 @@ TEST_F(SpoolStageTest, spillingDisabled) {
mock->enqueueAdvanced(makeRecord(1));
auto spool = makeSpool(std::move(mock),
0 /* maxAllowedMemoryUsageBytes */,
1 /* maxAllowedMemoryUsageBytes */,
boost::none /* maxAllowedDiskUsageBytes */);
WorkingSetID id;

View File

@ -38,7 +38,7 @@
#include "mongo/db/exec/document_value/document_metadata_fields.h"
#include "mongo/db/memory_tracking/operation_memory_usage_tracker.h"
#include "mongo/db/query/plan_executor_impl.h"
#include "mongo/db/query/query_stage_memory_limit_knobs_gen.h"
#include "mongo/db/query/stage_memory_limit_knobs/knobs.h"
#include "mongo/db/query/util/spill_util.h"
#include "mongo/db/record_id.h"
#include "mongo/db/sorter/sorter_template_defs.h"
@ -70,7 +70,7 @@ TextOrStage::TextOrStage(ExpressionContext* expCtx,
_keyPrefixSize(keyPrefixSize),
_ws(ws),
_memoryTracker(OperationMemoryUsageTracker::createSimpleMemoryUsageTrackerForStage(
*expCtx, internalTextOrStageMaxMemoryBytes.loadRelaxed())),
*expCtx, loadMemoryLimit(StageMemoryLimit::TextOrStageMaxMemoryBytes))),
_filter(filter),
_idRetrying(WorkingSet::INVALID_ID) {}

View File

@ -248,6 +248,7 @@ mongo_cc_library(
"//src/mongo/db/query:spill_util",
"//src/mongo/db/query/compiler/metadata:query_metadata",
"//src/mongo/db/query/compiler/physical_model/index_bounds",
"//src/mongo/db/query/stage_memory_limit_knobs",
"//src/mongo/db/sorter:sorter_base",
"//src/mongo/db/sorter:sorter_stats",
"//src/mongo/db/storage:encryption_hooks",

View File

@ -50,9 +50,9 @@
#include "mongo/db/query/collation/collator_interface.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/db/query/compiler/physical_model/query_solution/stage_types.h"
#include "mongo/db/query/query_stage_memory_limit_knobs_gen.h"
#include "mongo/db/query/stage_builder/sbe/gen_helpers.h"
#include "mongo/db/record_id.h"
#include "mongo/idl/server_parameter_test_util.h"
#include "mongo/platform/atomic_word.h"
#include "mongo/stdx/unordered_map.h"
#include "mongo/unittest/unittest.h"
@ -636,13 +636,8 @@ TEST_F(HashAggStageTest, HashAggBasicCountForceSpill) {
TEST_F(HashAggStageTest, HashAggBasicCountSpill) {
// We estimate the size of result row like {int64, int64} at 50B. Set the memory threshold to
// 64B so that exactly one row fits in memory.
auto defaultInternalQuerySBEAggApproxMemoryUseInBytesBeforeSpill =
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.load();
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.store(64);
ON_BLOCK_EXIT([&] {
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.store(
defaultInternalQuerySBEAggApproxMemoryUseInBytesBeforeSpill);
});
RAIIServerParameterControllerForTest maxMemoryLimit(
"internalQuerySlotBasedExecutionHashAggApproxMemoryUseInBytesBeforeSpill", 64);
auto ctx = makeCompileCtx();
@ -709,20 +704,12 @@ TEST_F(HashAggStageTest, HashAggBasicCountNoSpillIfNoMemCheck) {
// 64B so that exactly one row fits in memory and spill would be required. At the same time, set
// the memory check bounds to exceed the number of processed records so the checks are never run
// and the need to spill is never discovered.
auto defaultMemoryLimit = internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.load();
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.store(64);
auto defaultAtMost = internalQuerySBEAggMemoryCheckPerAdvanceAtMost.load();
internalQuerySBEAggMemoryCheckPerAdvanceAtMost.store(100);
auto defaultAtLeast = internalQuerySBEAggMemoryCheckPerAdvanceAtLeast.load();
internalQuerySBEAggMemoryCheckPerAdvanceAtLeast.store(100);
ON_BLOCK_EXIT([&] {
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.store(defaultMemoryLimit);
internalQuerySBEAggMemoryCheckPerAdvanceAtMost.store(defaultAtMost);
internalQuerySBEAggMemoryCheckPerAdvanceAtLeast.store(defaultAtLeast);
});
RAIIServerParameterControllerForTest maxMemoryLimit(
"internalQuerySlotBasedExecutionHashAggApproxMemoryUseInBytesBeforeSpill", 64);
RAIIServerParameterControllerForTest checkPerAdvanceAtMost(
"internalQuerySlotBasedExecutionHashAggMemoryCheckPerAdvanceAtMost", 100);
RAIIServerParameterControllerForTest checkPerAdvanceAtLeast(
"internalQuerySlotBasedExecutionHashAggMemoryCheckPerAdvanceAtLeast", 100);
auto ctx = makeCompileCtx();
@ -781,13 +768,8 @@ TEST_F(HashAggStageTest, HashAggBasicCountNoSpillIfNoMemCheck) {
TEST_F(HashAggStageTest, HashAggBasicCountSpillDouble) {
// We estimate the size of result row like {double, int64} at 50B. Set the memory threshold to
// 64B so that exactly one row fits in memory.
auto defaultInternalQuerySBEAggApproxMemoryUseInBytesBeforeSpill =
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.load();
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.store(64);
ON_BLOCK_EXIT([&] {
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.store(
defaultInternalQuerySBEAggApproxMemoryUseInBytesBeforeSpill);
});
RAIIServerParameterControllerForTest maxMemoryLimit(
"internalQuerySlotBasedExecutionHashAggApproxMemoryUseInBytesBeforeSpill", 64);
auto ctx = makeCompileCtx();
@ -850,13 +832,8 @@ TEST_F(HashAggStageTest, HashAggBasicCountSpillDouble) {
}
TEST_F(HashAggStageTest, HashAggBasicCountNoSpillWithNoGroupByDouble) {
auto defaultInternalQuerySBEAggApproxMemoryUseInBytesBeforeSpill =
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.load();
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.store(1);
ON_BLOCK_EXIT([&] {
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.store(
defaultInternalQuerySBEAggApproxMemoryUseInBytesBeforeSpill);
});
RAIIServerParameterControllerForTest maxMemoryLimit(
"internalQuerySlotBasedExecutionHashAggApproxMemoryUseInBytesBeforeSpill", 128);
auto ctx = makeCompileCtx();
@ -915,13 +892,8 @@ TEST_F(HashAggStageTest, HashAggBasicCountNoSpillWithNoGroupByDouble) {
TEST_F(HashAggStageTest, HashAggMultipleAccSpill) {
// We estimate the size of result row like {double, int64} at 59B. Set the memory threshold to
// 128B so that two rows fit in memory.
auto defaultInternalQuerySBEAggApproxMemoryUseInBytesBeforeSpill =
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.load();
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.store(128);
ON_BLOCK_EXIT([&] {
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.store(
defaultInternalQuerySBEAggApproxMemoryUseInBytesBeforeSpill);
});
RAIIServerParameterControllerForTest maxMemoryLimit(
"internalQuerySlotBasedExecutionHashAggApproxMemoryUseInBytesBeforeSpill", 128);
auto ctx = makeCompileCtx();
@ -995,14 +967,9 @@ TEST_F(HashAggStageTest, HashAggMultipleAccSpill) {
}
TEST_F(HashAggStageTest, HashAggMultipleAccSpillAllToDisk) {
// Set available memory to zero so all aggregated rows have to be spilled.
auto defaultInternalQuerySBEAggApproxMemoryUseInBytesBeforeSpill =
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.load();
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.store(0);
ON_BLOCK_EXIT([&] {
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.store(
defaultInternalQuerySBEAggApproxMemoryUseInBytesBeforeSpill);
});
// Set available memory to 1 byte so all aggregated rows have to be spilled.
RAIIServerParameterControllerForTest maxMemoryLimit(
"internalQuerySlotBasedExecutionHashAggApproxMemoryUseInBytesBeforeSpill", 1);
auto ctx = makeCompileCtx();
@ -1171,13 +1138,8 @@ TEST_F(HashAggStageTest, HashAggMultipleAccForceSpill) {
TEST_F(HashAggStageTest, HashAggMultipleAccForceSpillAfterSpill) {
// We estimate the size of result row like {double, int64} at 59B. Set the memory threshold to
// 128B so that two rows fit in memory.
auto defaultInternalQuerySBEAggApproxMemoryUseInBytesBeforeSpill =
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.load();
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.store(128);
ON_BLOCK_EXIT([&] {
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.store(
defaultInternalQuerySBEAggApproxMemoryUseInBytesBeforeSpill);
});
RAIIServerParameterControllerForTest maxMemoryLimit(
"internalQuerySlotBasedExecutionHashAggApproxMemoryUseInBytesBeforeSpill", 128);
auto ctx = makeCompileCtx();
@ -1262,13 +1224,8 @@ TEST_F(HashAggStageTest, HashAggSum10Groups) {
// estimated size is >= 128. This should spilt the number of ints between the hash table and
// the record store somewhat evenly.
const auto memLimit = 128;
auto defaultInternalQuerySBEAggApproxMemoryUseInBytesBeforeSpill =
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.load();
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.store(memLimit);
ON_BLOCK_EXIT([&] {
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.store(
defaultInternalQuerySBEAggApproxMemoryUseInBytesBeforeSpill);
});
RAIIServerParameterControllerForTest maxMemoryLimit(
"internalQuerySlotBasedExecutionHashAggApproxMemoryUseInBytesBeforeSpill", memLimit);
auto ctx = makeCompileCtx();

View File

@ -33,6 +33,8 @@
#include "mongo/db/exec/sbe/sbe_hash_lookup_shared_test.h"
#include "mongo/idl/server_parameter_test_util.h"
namespace mongo::sbe {
void HashLookupSharedTest::prepareAndEvalStageWithReopen(
CompileCtx* ctx,
@ -70,13 +72,8 @@ void HashLookupSharedTest::prepareAndEvalStageWithReopen(
stage->close();
// Execute the stage with spilling to disk.
auto defaultInternalQuerySBELookupApproxMemoryUseInBytesBeforeSpill =
internalQuerySBELookupApproxMemoryUseInBytesBeforeSpill.load();
internalQuerySBELookupApproxMemoryUseInBytesBeforeSpill.store(10);
ON_BLOCK_EXIT([&] {
internalQuerySBELookupApproxMemoryUseInBytesBeforeSpill.store(
defaultInternalQuerySBELookupApproxMemoryUseInBytesBeforeSpill);
});
RAIIServerParameterControllerForTest maxMemoryLimit(
"internalQuerySlotBasedExecutionHashLookupApproxMemoryUseInBytesBeforeSpill", 10);
// Run the stage after the knob is set and spill to disk. We need to hold a global IS lock
// to read from WT.

View File

@ -53,7 +53,6 @@
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/db/query/compiler/physical_model/query_solution/stage_types.h"
#include "mongo/db/query/query_knobs_gen.h"
#include "mongo/db/query/query_stage_memory_limit_knobs_gen.h"
#include "mongo/db/query/stage_builder/sbe/gen_helpers.h"
#include "mongo/platform/atomic_word.h"
#include "mongo/unittest/golden_test.h"

View File

@ -34,7 +34,7 @@
#include "mongo/db/exec/sbe/stages/hashagg_base.h"
#include "mongo/db/exec/sbe/values/block_interface.h"
#include "mongo/db/exec/sbe/values/value.h"
#include "mongo/db/query/query_stage_memory_limit_knobs_gen.h"
#include "mongo/db/query/stage_memory_limit_knobs/knobs.h"
#include "mongo/db/stats/counters.h"
#include "mongo/db/storage/kv/kv_engine.h"
#include "mongo/db/storage/storage_engine.h"
@ -289,7 +289,7 @@ void BlockHashAggStage::prepare(CompileCtx& ctx) {
_compiled = true;
_memoryTracker = OperationMemoryUsageTracker::createSimpleMemoryUsageTrackerForSBE(
_opCtx, internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.load());
_opCtx, loadMemoryLimit(StageMemoryLimit::QuerySBEAggApproxMemoryUseInBytesBeforeSpill));
}
value::SlotAccessor* BlockHashAggStage::getAccessor(CompileCtx& ctx, value::SlotId slot) {

View File

@ -39,7 +39,7 @@
#include "mongo/db/exec/sbe/util/debug_print.h"
#include "mongo/db/exec/sbe/values/value.h"
#include "mongo/db/query/collation/collator_interface.h"
#include "mongo/db/query/query_stage_memory_limit_knobs_gen.h"
#include "mongo/db/query/stage_memory_limit_knobs/knobs.h"
#include "mongo/db/record_id.h"
#include "mongo/db/service_context.h"
#include "mongo/db/stats/counters.h"
@ -213,7 +213,7 @@ void HashAggStage::prepare(CompileCtx& ctx) {
_compiled = true;
_memoryTracker = OperationMemoryUsageTracker::createSimpleMemoryUsageTrackerForSBE(
_opCtx, internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.load());
_opCtx, loadMemoryLimit(StageMemoryLimit::QuerySBEAggApproxMemoryUseInBytesBeforeSpill));
}
value::SlotAccessor* HashAggStage::getAccessor(CompileCtx& ctx, value::SlotId slot) {

View File

@ -409,7 +409,8 @@ boost::optional<std::pair<value::TypeTags, value::Value>> LookupHashTable::getVa
} // HashLookupUnwindStage::getValueAtIndex
void LookupHashTable::reset(bool fromClose) {
_memoryUseInBytesBeforeSpill = internalQuerySBELookupApproxMemoryUseInBytesBeforeSpill.load();
_memoryUseInBytesBeforeSpill =
loadMemoryLimit(StageMemoryLimit::QuerySBELookupApproxMemoryUseInBytesBeforeSpill);
_memoryHt = boost::none;
if (_recordStoreHt) {

View File

@ -36,7 +36,7 @@
#include "mongo/db/exec/sbe/values/value.h"
#include "mongo/db/operation_context.h"
#include "mongo/db/query/collation/collator_interface.h"
#include "mongo/db/query/query_stage_memory_limit_knobs_gen.h"
#include "mongo/db/query/stage_memory_limit_knobs/knobs.h"
#include <cstddef>
#include <cstdint>
@ -324,7 +324,7 @@ private:
// Memory tracking and spilling to disk.
long long _memoryUseInBytesBeforeSpill =
internalQuerySBELookupApproxMemoryUseInBytesBeforeSpill.load();
loadMemoryLimit(StageMemoryLimit::QuerySBELookupApproxMemoryUseInBytesBeforeSpill);
// The portion of the inner collection hash table that has spilled to disk.
std::unique_ptr<SpillingStore> _recordStoreHt;

View File

@ -33,7 +33,7 @@
#include "mongo/db/exec/sbe/stages/stages.h"
#include "mongo/db/exec/sbe/util/spilling.h"
#include "mongo/db/exec/sbe/vm/vm.h"
#include "mongo/db/query/query_stage_memory_limit_knobs_gen.h"
#include "mongo/db/query/stage_memory_limit_knobs/knobs.h"
#include <bit>
@ -394,7 +394,8 @@ private:
// The memory size for each window accumulator state.
std::vector<std::vector<WindowStateMemoryEstimator>> _windowStateMemoryEstimators;
// Memory threshold before spilling.
const size_t _memoryThreshold = internalDocumentSourceSetWindowFieldsMaxMemoryBytes.load();
const size_t _memoryThreshold =
loadMemoryLimit(StageMemoryLimit::DocumentSourceSetWindowFieldsMaxMemoryBytes);
// The failpoint counter to force spilling, incremented for every window function update,
// every document.

View File

@ -734,6 +734,7 @@ mongo_cc_library(
"//src/mongo/db/query/search:mongot_options",
"//src/mongo/db/query/search:search_index_common",
"//src/mongo/db/query/search:search_index_process_interface",
"//src/mongo/db/query/stage_memory_limit_knobs",
"//src/mongo/db/query/util:query_string_util",
"//src/mongo/db/repl:apply_ops_command_info",
"//src/mongo/db/repl:image_collection_entry",

View File

@ -41,7 +41,7 @@
#include "mongo/db/pipeline/lite_parsed_document_source.h"
#include "mongo/db/query/allowed_contexts.h"
#include "mongo/db/query/compiler/dependency_analysis/expression_dependencies.h"
#include "mongo/db/query/query_stage_memory_limit_knobs_gen.h"
#include "mongo/db/query/stage_memory_limit_knobs/knobs.h"
#include "mongo/db/sorter/sorter_template_defs.h"
#include "mongo/db/stats/counters.h"
#include "mongo/util/assert_util.h"
@ -670,7 +670,7 @@ intrusive_ptr<DocumentSource> DocumentSourceBucketAuto::createFromBson(
pExpCtx,
groupByExpression,
numBuckets.value(),
internalDocumentSourceBucketAutoMaxMemoryBytes.loadRelaxed(),
loadMemoryLimit(StageMemoryLimit::DocumentSourceBucketAutoMaxMemoryBytes),
std::move(accumulationStatements),
granularityRounder);
}

View File

@ -45,7 +45,7 @@
#include "mongo/db/pipeline/expression_context_for_test.h"
#include "mongo/db/query/compiler/dependency_analysis/dependencies.h"
#include "mongo/db/query/explain_options.h"
#include "mongo/db/query/query_stage_memory_limit_knobs_gen.h"
#include "mongo/db/query/stage_memory_limit_knobs/knobs.h"
#include "mongo/idl/server_parameter_test_util.h"
#include "mongo/unittest/temp_dir.h"
#include "mongo/unittest/unittest.h"
@ -508,7 +508,7 @@ TEST_F(BucketAutoTests, ShouldBeAbleToForceSpillWhileLoadingDocuments) {
expCtx,
groupByExpression,
numBuckets,
internalDocumentSourceBucketAutoMaxMemoryBytes.loadRelaxed());
loadMemoryLimit(StageMemoryLimit::DocumentSourceBucketAutoMaxMemoryBytes));
string largeStr(1000, 'x');
auto mock =
@ -567,7 +567,7 @@ TEST_F(BucketAutoTests, ShouldBeAbleToForceSpillWhileReturningDocuments) {
expCtx,
groupByExpression,
numBuckets,
internalDocumentSourceBucketAutoMaxMemoryBytes.loadRelaxed());
loadMemoryLimit(StageMemoryLimit::DocumentSourceBucketAutoMaxMemoryBytes));
string largeStr(1000, 'x');
auto mock = DocumentSourceMock::createForTest({Document{{"a", 0}, {"largeStr", largeStr}},
@ -724,13 +724,14 @@ TEST_F(BucketAutoTests, FailsWithInvalidNumberOfBuckets) {
// Use the create() helper.
const int numBuckets = 0;
ASSERT_THROWS_CODE(DocumentSourceBucketAuto::create(
getExpCtx(),
ExpressionConstant::create(getExpCtxRaw(), Value(0)),
numBuckets,
internalDocumentSourceBucketAutoMaxMemoryBytes.loadRelaxed()),
AssertionException,
40243);
ASSERT_THROWS_CODE(
DocumentSourceBucketAuto::create(
getExpCtx(),
ExpressionConstant::create(getExpCtxRaw(), Value(0)),
numBuckets,
loadMemoryLimit(StageMemoryLimit::DocumentSourceBucketAutoMaxMemoryBytes)),
AssertionException,
40243);
}
TEST_F(BucketAutoTests, FailsWithNonOrInvalidExpressionGroupBy) {

View File

@ -49,7 +49,7 @@
#include "mongo/db/query/datetime/date_time_support.h"
#include "mongo/db/query/query_knobs_gen.h"
#include "mongo/db/query/query_shape/serialization_options.h"
#include "mongo/db/query/query_stage_memory_limit_knobs_gen.h"
#include "mongo/db/query/stage_memory_limit_knobs/knobs.h"
#include "mongo/platform/atomic_word.h"
#include "mongo/util/assert_util.h"
#include "mongo/util/intrusive_counter.h"
@ -335,7 +335,7 @@ public:
RangeStatement range)
: DocumentSource(kStageName, pExpCtx),
exec::agg::Stage(kStageName, pExpCtx),
_memTracker(internalDocumentSourceDensifyMaxMemoryBytes.load()),
_memTracker(loadMemoryLimit(StageMemoryLimit::DocumentSourceDensifyMaxMemoryBytes)),
_field(std::move(field)),
_partitions(std::move(partitions)),
_range(std::move(range)),

View File

@ -50,7 +50,7 @@
#include "mongo/db/query/compiler/dependency_analysis/dependencies.h"
#include "mongo/db/query/query_knobs_gen.h"
#include "mongo/db/query/query_shape/serialization_options.h"
#include "mongo/db/query/query_stage_memory_limit_knobs_gen.h"
#include "mongo/db/query/stage_memory_limit_knobs/knobs.h"
#include "mongo/platform/atomic_word.h"
#include "mongo/stdx/unordered_set.h"
#include "mongo/util/intrusive_counter.h"
@ -125,7 +125,7 @@ public:
static boost::intrusive_ptr<DocumentSourceFacet> create(
std::vector<FacetPipeline> facetPipelines,
const boost::intrusive_ptr<ExpressionContext>& expCtx,
size_t bufferSizeBytes = internalQueryFacetBufferSizeBytes.load(),
size_t bufferSizeBytes = loadMemoryLimit(StageMemoryLimit::QueryFacetBufferSizeBytes),
size_t maxOutputDocBytes = internalQueryFacetMaxOutputDocSizeBytes.load());
/**

View File

@ -52,7 +52,7 @@
#include "mongo/db/pipeline/sort_reorder_helpers.h"
#include "mongo/db/query/allowed_contexts.h"
#include "mongo/db/query/query_knobs_gen.h"
#include "mongo/db/query/query_stage_memory_limit_knobs_gen.h"
#include "mongo/db/query/stage_memory_limit_knobs/knobs.h"
#include "mongo/db/s/sharding_state.h"
#include "mongo/db/stats/counters.h"
#include "mongo/db/views/resolved_view.h"
@ -820,7 +820,7 @@ DocumentSourceGraphLookUp::DocumentSourceGraphLookUp(
_memoryUsageTracker(OperationMemoryUsageTracker::createMemoryUsageTrackerForStage(
*expCtx,
expCtx->getAllowDiskUse(),
internalDocumentSourceGraphLookupMaxMemoryBytes.load())),
loadMemoryLimit(StageMemoryLimit::DocumentSourceGraphLookupMaxMemoryBytes))),
_queue(pExpCtx.get(), &_memoryUsageTracker),
_visitedDocuments(pExpCtx.get(), &_memoryUsageTracker, "VisitedDocumentsMap"),
_visitedFromValues(pExpCtx.get(), &_memoryUsageTracker, "VisitedFromValuesSet"),
@ -865,7 +865,7 @@ DocumentSourceGraphLookUp::DocumentSourceGraphLookUp(
_memoryUsageTracker(OperationMemoryUsageTracker::createMemoryUsageTrackerForStage(
*newExpCtx,
newExpCtx->getAllowDiskUse(),
internalDocumentSourceGraphLookupMaxMemoryBytes.load())),
loadMemoryLimit(StageMemoryLimit::DocumentSourceGraphLookupMaxMemoryBytes))),
_queue(pExpCtx.get(), &_memoryUsageTracker),
_visitedDocuments(pExpCtx.get(), &_memoryUsageTracker, "VisitedDocumentsMap"),
_visitedFromValues(pExpCtx.get(), &_memoryUsageTracker, "VisitedFromValuesSet"),

View File

@ -56,7 +56,7 @@
#include "mongo/db/query/compiler/dependency_analysis/dependencies.h"
#include "mongo/db/query/compiler/dependency_analysis/expression_dependencies.h"
#include "mongo/db/query/explain_options.h"
#include "mongo/db/query/query_stage_memory_limit_knobs_gen.h"
#include "mongo/db/query/stage_memory_limit_knobs/knobs.h"
#include "mongo/platform/atomic_word.h"
#include "mongo/util/assert_util.h"
@ -262,8 +262,9 @@ DocumentSourceGroupBase::DocumentSourceGroupBase(
: DocumentSource(stageName, expCtx),
_groupProcessor(std::make_shared<GroupProcessor>(
expCtx,
maxMemoryUsageBytes ? *maxMemoryUsageBytes
: internalDocumentSourceGroupMaxMemoryBytes.load())),
maxMemoryUsageBytes
? *maxMemoryUsageBytes
: loadMemoryLimit(StageMemoryLimit::DocumentSourceGroupMaxMemoryBytes))),
_sbeCompatibility(SbeCompatibility::notCompatible) {}
namespace {

View File

@ -76,7 +76,7 @@
#include "mongo/db/query/explain_options.h"
#include "mongo/db/query/plan_summary_stats.h"
#include "mongo/db/query/query_knobs_gen.h"
#include "mongo/db/query/query_stage_memory_limit_knobs_gen.h"
#include "mongo/db/query/stage_memory_limit_knobs/knobs.h"
#include "mongo/db/s/sharding_state.h"
#include "mongo/db/stats/counters.h"
#include "mongo/db/views/resolved_view.h"
@ -333,7 +333,7 @@ void DocumentSourceLookUp::resolvedPipelineHelper(
if (localForeignFields != boost::none) {
std::tie(_localField, _foreignField) = *localForeignFields;
} else {
_cache.emplace(internalDocumentSourceLookupCacheSizeBytes.load());
_cache.emplace(loadMemoryLimit(StageMemoryLimit::DocumentSourceLookupCacheSizeBytes));
}
return;
}
@ -358,7 +358,7 @@ void DocumentSourceLookUp::resolvedPipelineHelper(
// When local/foreignFields are included, we cannot enable the cache because the $match
// is a correlated prefix that will not be detected. Here, local/foreignFields are absent,
// so we enable the cache.
_cache.emplace(internalDocumentSourceLookupCacheSizeBytes.load());
_cache.emplace(loadMemoryLimit(StageMemoryLimit::DocumentSourceLookupCacheSizeBytes));
// Add the user pipeline to '_resolvedPipeline' after any potential view prefix and $match
_resolvedPipeline.insert(_resolvedPipeline.end(), pipeline.begin(), pipeline.end());

View File

@ -52,7 +52,7 @@
#include "mongo/db/pipeline/sharded_agg_helpers_targeting_policy.h"
#include "mongo/db/query/explain_options.h"
#include "mongo/db/query/query_knobs_gen.h"
#include "mongo/db/query/query_stage_memory_limit_knobs_gen.h"
#include "mongo/db/query/stage_memory_limit_knobs/knobs.h"
#include "mongo/db/repl/member_state.h"
#include "mongo/db/repl/repl_settings.h"
#include "mongo/db/repl/replication_coordinator.h"
@ -90,7 +90,8 @@ protected:
}
};
const long long kDefaultMaxCacheSize = internalDocumentSourceLookupCacheSizeBytes.load();
const long long kDefaultMaxCacheSize =
loadMemoryLimit(StageMemoryLimit::DocumentSourceLookupCacheSizeBytes);
const auto kExplain = SerializationOptions{
.verbosity = boost::make_optional(ExplainOptions::Verbosity::kQueryPlanner)};

View File

@ -57,7 +57,7 @@
#include "mongo/db/pipeline/search/document_source_vector_search.h"
#include "mongo/db/pipeline/search/search_helper.h"
#include "mongo/db/query/allowed_contexts.h"
#include "mongo/db/query/query_stage_memory_limit_knobs_gen.h"
#include "mongo/db/query/stage_memory_limit_knobs/knobs.h"
#include "mongo/logv2/log.h"
#include "mongo/util/string_map.h"
@ -149,7 +149,7 @@ boost::intrusive_ptr<DocumentSource> setWindowFields(const auto& expCtx,
rankFieldName,
window_function::Expression::parse(
BSON("$rank" << BSONObj()), dummySortPattern, expCtx.get())}},
internalDocumentSourceSetWindowFieldsMaxMemoryBytes.load(),
loadMemoryLimit(StageMemoryLimit::DocumentSourceSetWindowFieldsMaxMemoryBytes),
SbeCompatibility::notCompatible);
}

View File

@ -44,7 +44,7 @@
#include "mongo/db/pipeline/lite_parsed_document_source.h"
#include "mongo/db/query/allowed_contexts.h"
#include "mongo/db/query/compiler/dependency_analysis/expression_dependencies.h"
#include "mongo/db/query/query_stage_memory_limit_knobs_gen.h"
#include "mongo/db/query/stage_memory_limit_knobs/knobs.h"
#include "mongo/db/version_context.h"
#include "mongo/util/assert_util.h"
#include "mongo/util/str.h"
@ -231,7 +231,7 @@ boost::intrusive_ptr<DocumentSource> buildSetWindowFieldsStage(
BSON("$minMaxScaler" << BSON("input" << BSON("$meta" << "score"))),
sortPattern,
expCtx.get())}},
internalDocumentSourceSetWindowFieldsMaxMemoryBytes.load(),
loadMemoryLimit(StageMemoryLimit::DocumentSourceSetWindowFieldsMaxMemoryBytes),
SbeCompatibility::notCompatible);
}

View File

@ -49,7 +49,7 @@
#include "mongo/db/pipeline/search/document_source_search.h"
#include "mongo/db/pipeline/search/document_source_vector_search.h"
#include "mongo/db/query/allowed_contexts.h"
#include "mongo/db/query/query_stage_memory_limit_knobs_gen.h"
#include "mongo/db/query/stage_memory_limit_knobs/knobs.h"
#include <boost/smart_ptr/intrusive_ptr.hpp>
@ -366,7 +366,7 @@ boost::intrusive_ptr<DocumentSource> builtSetWindowFieldsStageForMinMaxScalerNor
internalFieldsScore, // output field
window_function::Expression::parse(
BSON("$minMaxScaler" << BSON("input" << dollarScore)), sortPattern, expCtx.get())}},
internalDocumentSourceSetWindowFieldsMaxMemoryBytes.load(),
loadMemoryLimit(StageMemoryLimit::DocumentSourceSetWindowFieldsMaxMemoryBytes),
SbeCompatibility::notCompatible);
}

View File

@ -34,7 +34,7 @@
#include "mongo/db/pipeline/aggregation_context_fixture.h"
#include "mongo/db/pipeline/document_source_mock.h"
#include "mongo/db/query/explain_options.h"
#include "mongo/db/query/query_stage_memory_limit_knobs_gen.h"
#include "mongo/db/query/stage_memory_limit_knobs/knobs.h"
#include "mongo/platform/atomic_word.h"
#include "mongo/unittest/unittest.h"
@ -49,7 +49,8 @@ namespace {
// This provides access to getExpCtx(), but we'll use a different name for this test suite.
using DocumentSourceSequentialDocumentCacheTest = AggregationContextFixture;
const long long kDefaultMaxCacheSize = internalDocumentSourceLookupCacheSizeBytes.load();
const long long kDefaultMaxCacheSize =
loadMemoryLimit(StageMemoryLimit::DocumentSourceLookupCacheSizeBytes);
TEST_F(DocumentSourceSequentialDocumentCacheTest, ReturnsEOFOnSubsequentCallsAfterSourceExhausted) {
SequentialDocumentCache cache(kDefaultMaxCacheSize);

View File

@ -52,7 +52,7 @@
#include "mongo/db/query/compiler/logical_model/sort_pattern/sort_pattern.h"
#include "mongo/db/query/explain_options.h"
#include "mongo/db/query/query_knobs_gen.h"
#include "mongo/db/query/query_stage_memory_limit_knobs_gen.h"
#include "mongo/db/query/stage_memory_limit_knobs/knobs.h"
#include "mongo/db/transaction_resources.h"
#include "mongo/idl/idl_parser.h"
#include "mongo/logv2/log.h"
@ -307,7 +307,7 @@ list<intrusive_ptr<DocumentSource>> document_source_set_window_fields::create(
simplePartitionByExpr,
std::move(sortBy),
std::move(outputFields),
internalDocumentSourceSetWindowFieldsMaxMemoryBytes.load(),
loadMemoryLimit(StageMemoryLimit::DocumentSourceSetWindowFieldsMaxMemoryBytes),
sbeCompatibility));
// $unset
@ -432,7 +432,7 @@ boost::intrusive_ptr<DocumentSource> DocumentSourceInternalSetWindowFields::crea
partitionBy,
sortBy,
outputFields,
internalDocumentSourceSetWindowFieldsMaxMemoryBytes.load(),
loadMemoryLimit(StageMemoryLimit::DocumentSourceSetWindowFieldsMaxMemoryBytes),
sbeCompatibility);
}

View File

@ -45,7 +45,7 @@
#include "mongo/db/query/allowed_contexts.h"
#include "mongo/db/query/explain_options.h"
#include "mongo/db/query/query_shape/serialization_options.h"
#include "mongo/db/query/query_stage_memory_limit_knobs_gen.h"
#include "mongo/db/query/stage_memory_limit_knobs/knobs.h"
#include "mongo/db/sorter/sorter_template_defs.h"
#include "mongo/platform/compiler.h"
#include "mongo/util/assert_util.h"
@ -139,14 +139,15 @@ DocumentSourceSort::DocumentSourceSort(const boost::intrusive_ptr<ExpressionCont
_sortExecutor(std::make_shared<SortExecutor<Document>>(
sortOrder,
options.limit,
options.maxMemoryUsageBytes.value_or(internalQueryMaxBlockingSortMemoryUsageBytes.load()),
options.maxMemoryUsageBytes.value_or(
loadMemoryLimit(StageMemoryLimit::QueryMaxBlockingSortMemoryUsageBytes)),
pExpCtx->getTempDir(),
pExpCtx->getAllowDiskUse())),
_memoryTracker(std::make_shared<SimpleMemoryUsageTracker>(
OperationMemoryUsageTracker::createSimpleMemoryUsageTrackerForStage(
*pExpCtx,
options.maxMemoryUsageBytes.value_or(
internalQueryMaxBlockingSortMemoryUsageBytes.load())))),
loadMemoryLimit(StageMemoryLimit::QueryMaxBlockingSortMemoryUsageBytes))))),
_outputSortKeyMetadata(options.outputSortKeyMetadata) {
uassert(15976,
"$sort stage must have at least one sort key",
@ -397,7 +398,8 @@ boost::intrusive_ptr<DocumentSourceSort> DocumentSourceSort::createBoundedSort(
auto ds = DocumentSourceSort::create(expCtx, pat);
SortOptions opts;
opts.maxMemoryUsageBytes = internalQueryMaxBlockingSortMemoryUsageBytes.load();
opts.maxMemoryUsageBytes =
loadMemoryLimit(StageMemoryLimit::QueryMaxBlockingSortMemoryUsageBytes);
if (expCtx->getAllowDiskUse()) {
opts.extSortAllowed = true;
opts.tempDir = expCtx->getTempDir();
@ -498,7 +500,8 @@ boost::intrusive_ptr<DocumentSourceSort> DocumentSourceSort::parseBoundedSort(
auto ds = DocumentSourceSort::create(expCtx, pat);
SortOptions opts;
opts.MaxMemoryUsageBytes(internalQueryMaxBlockingSortMemoryUsageBytes.load());
opts.MaxMemoryUsageBytes(
loadMemoryLimit(StageMemoryLimit::QueryMaxBlockingSortMemoryUsageBytes));
if (expCtx->getAllowDiskUse()) {
opts.ExtSortAllowed(true);
opts.TempDir(expCtx->getTempDir());

View File

@ -32,7 +32,7 @@
#include "mongo/db/exec/agg/stage.h"
#include "mongo/db/exec/document_value/document.h"
#include "mongo/db/pipeline/document_source.h"
#include "mongo/db/query/query_stage_memory_limit_knobs_gen.h"
#include "mongo/db/query/stage_memory_limit_knobs/knobs.h"
#include "mongo/platform/atomic_word.h"
#include "mongo/util/intrusive_counter.h"
@ -59,7 +59,8 @@ public:
* 'bufferSizeBytes' is a soft cap, and may be exceeded by one document's worth (~16MB).
*/
static boost::intrusive_ptr<TeeBuffer> create(
size_t nConsumers, int bufferSizeBytes = internalQueryFacetBufferSizeBytes.load());
size_t nConsumers,
int bufferSizeBytes = loadMemoryLimit(StageMemoryLimit::QueryFacetBufferSizeBytes));
void setSource(exec::agg::Stage* source) {
_source = source;

View File

@ -29,6 +29,7 @@ mongo_cc_library(
"//src/mongo:base",
"//src/mongo/db:service_context",
"//src/mongo/db/query/datetime:init_timezone_data",
"//src/mongo/db/query/stage_memory_limit_knobs",
],
)
@ -226,14 +227,6 @@ idl_generator(
],
)
idl_generator(
name = "query_stage_memory_limit_knobs_gen",
src = "query_stage_memory_limit_knobs.idl",
deps = [
"//src/mongo/db:basic_types_gen",
],
)
mongo_cc_library(
name = "plan_yield_policy",
srcs = [
@ -331,19 +324,10 @@ mongo_cc_library(
)
mongo_cc_library(
name = "query_knobs",
name = "on_parameter_change_updaters",
srcs = [
"framework_control.cpp",
"plan_ranker_mode.cpp",
"query_feature_flags_gen",
"query_knobs_gen",
"query_stage_memory_limit_knobs_gen",
"sampling_ce_method.cpp",
"sampling_confidence_interval.cpp",
"sbe_hashAgg_increased_spilling_mode.cpp",
"//src/mongo/db/query/plan_cache:sbe_plan_cache_on_parameter_change.cpp",
"//src/mongo/db/query/query_stats:query_stats_on_parameter_change.cpp",
"//src/mongo/db/query/query_stats:rate_limiting.h",
],
hdrs = [
"//src/mongo/db/query/plan_cache:sbe_plan_cache_on_parameter_change.h",
@ -353,6 +337,24 @@ mongo_cc_library(
":memory_util",
"//src/mongo/db:server_base",
"//src/mongo/db:service_context",
],
)
mongo_cc_library(
name = "query_knobs",
srcs = [
"framework_control.cpp",
"plan_ranker_mode.cpp",
"query_feature_flags_gen",
"query_knobs_gen",
"sampling_ce_method.cpp",
"sampling_confidence_interval.cpp",
"sbe_hashAgg_increased_spilling_mode.cpp",
"//src/mongo/db/query/query_stats:rate_limiting.h",
],
deps = [
":on_parameter_change_updaters",
"//src/mongo/db:server_base",
"//src/mongo/idl:cluster_server_parameter",
],
)

View File

@ -47,7 +47,7 @@
#include "mongo/db/query/compiler/physical_model/interval/interval.h"
#include "mongo/db/query/compiler/physical_model/query_solution/query_solution_helpers.h"
#include "mongo/db/query/query_planner_common.h"
#include "mongo/db/query/query_stage_memory_limit_knobs_gen.h"
#include "mongo/db/query/stage_memory_limit_knobs/knobs.h"
#include <algorithm>
#include <queue>
@ -1467,7 +1467,7 @@ std::unique_ptr<QuerySolutionNode> SortNodeSimple::clone() const {
}
uint64_t SortNode::_loadMaxMemoryUsageBytes() {
return internalQueryMaxBlockingSortMemoryUsageBytes.loadRelaxed();
return loadMemoryLimit(StageMemoryLimit::QueryMaxBlockingSortMemoryUsageBytes);
}
//

View File

@ -33,7 +33,7 @@
#include "mongo/db/curop.h"
#include "mongo/db/query/query_knob_configuration.h"
#include "mongo/db/query/query_knobs_gen.h"
#include "mongo/db/query/query_stage_memory_limit_knobs_gen.h"
#include "mongo/db/query/stage_memory_limit_knobs/knobs.h"
#include "mongo/db/server_options.h"
#include "mongo/db/server_parameter.h"
#include "mongo/util/net/socket_utils.h"
@ -55,21 +55,14 @@ void generateServerInfo(BSONObjBuilder* out) {
void generateServerParameters(const boost::intrusive_ptr<ExpressionContext>& expCtx,
BSONObjBuilder* out) {
BSONObjBuilder serverBob(out->subobjStart("serverParameters"));
out->appendNumber("internalQueryFacetBufferSizeBytes",
internalQueryFacetBufferSizeBytes.load());
appendStageMemoryLimitsToExplain(*out);
out->appendNumber("internalQueryFacetMaxOutputDocSizeBytes",
internalQueryFacetMaxOutputDocSizeBytes.load());
out->appendNumber("internalLookupStageIntermediateDocumentMaxSizeBytes",
internalLookupStageIntermediateDocumentMaxSizeBytes.load());
out->appendNumber("internalDocumentSourceGroupMaxMemoryBytes",
internalDocumentSourceGroupMaxMemoryBytes.load());
out->appendNumber("internalQueryMaxBlockingSortMemoryUsageBytes",
internalQueryMaxBlockingSortMemoryUsageBytes.load());
out->appendNumber("internalQueryProhibitBlockingMergeOnMongoS",
internalQueryProhibitBlockingMergeOnMongoS.load());
out->appendNumber("internalQueryMaxAddToSetBytes", internalQueryMaxAddToSetBytes.load());
out->appendNumber("internalDocumentSourceSetWindowFieldsMaxMemoryBytes",
internalDocumentSourceSetWindowFieldsMaxMemoryBytes.load());
auto queryControl = expCtx->getQueryKnobConfiguration().getInternalQueryFrameworkControlForOp();
out->append("internalQueryFrameworkControl", QueryFrameworkControl_serializer(queryControl));
out->appendNumber("internalQueryPlannerIgnoreIndexWithCollationForRegex",

View File

@ -0,0 +1,33 @@
load("//bazel:mongo_src_rules.bzl", "idl_generator", "mongo_cc_library")
package(default_visibility = ["//visibility:public"])
exports_files(
glob([
"*.h",
"*.cpp",
]),
)
idl_generator(
name = "stage_memory_limit_knobs_gen",
src = "knobs.idl",
deps = [
"//src/mongo/db:basic_types_gen",
],
)
mongo_cc_library(
name = "stage_memory_limit_knobs",
srcs = [
"knobs.cpp",
"stage_memory_limit_knobs_gen",
],
hdrs = [
"knobs.h",
],
deps = [
"//src/mongo/db:server_base",
"//src/mongo/db/query:on_parameter_change_updaters",
],
)

View File

@ -0,0 +1,8 @@
version: 1.0.0
filters:
- "*":
approvers:
- 10gen/query-execution
- "OWNERS.yml":
approvers:
- 10gen/query-execution-staff-leads

View File

@ -0,0 +1,86 @@
/**
* Copyright (C) 2025-present MongoDB, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Server Side Public License, version 1,
* as published by MongoDB, Inc.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Server Side Public License for more details.
*
* You should have received a copy of the Server Side Public License
* along with this program. If not, see
* <http://www.mongodb.com/licensing/server-side-public-license>.
*
* As a special exception, the copyright holders give permission to link the
* code of portions of this program with the OpenSSL library under certain
* conditions as described in each individual source file and distribute
* linked combinations including the program with the OpenSSL library. You
* must comply with the Server Side Public License in all respects for
* all of the code used other than as permitted herein. If you modify file(s)
* with this exception, you may extend this exception to your version of the
* file(s), but you are not obligated to do so. If you do not wish to do so,
* delete this exception statement from your version. If you delete this
* exception statement from all source files in the program, then also delete
* it in the license file.
*/
#include "mongo/db/query/stage_memory_limit_knobs/knobs.h"
#include "mongo/db/query/stage_memory_limit_knobs/knobs_gen.h"
namespace mongo {
namespace {
AtomicWord<long long>& getMemoryLimitKnob(StageMemoryLimit stage) {
switch (stage) {
case StageMemoryLimit::DocumentSourceLookupCacheSizeBytes:
return internalDocumentSourceLookupCacheSizeBytes;
case StageMemoryLimit::DocumentSourceGraphLookupMaxMemoryBytes:
return internalDocumentSourceGraphLookupMaxMemoryBytes;
case StageMemoryLimit::DocumentSourceGroupMaxMemoryBytes:
return internalDocumentSourceGroupMaxMemoryBytes;
case StageMemoryLimit::DocumentSourceSetWindowFieldsMaxMemoryBytes:
return internalDocumentSourceSetWindowFieldsMaxMemoryBytes;
case StageMemoryLimit::DocumentSourceBucketAutoMaxMemoryBytes:
return internalDocumentSourceBucketAutoMaxMemoryBytes;
case StageMemoryLimit::DocumentSourceDensifyMaxMemoryBytes:
return internalDocumentSourceDensifyMaxMemoryBytes;
case StageMemoryLimit::QueryFacetBufferSizeBytes:
return internalQueryFacetBufferSizeBytes;
case StageMemoryLimit::TextOrStageMaxMemoryBytes:
return internalTextOrStageMaxMemoryBytes;
case StageMemoryLimit::QuerySBELookupApproxMemoryUseInBytesBeforeSpill:
return internalQuerySBELookupApproxMemoryUseInBytesBeforeSpill;
case StageMemoryLimit::QuerySBEAggApproxMemoryUseInBytesBeforeSpill:
return internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill;
case StageMemoryLimit::QueryMaxSpoolMemoryUsageBytes:
return internalQueryMaxSpoolMemoryUsageBytes;
case StageMemoryLimit::QueryMaxBlockingSortMemoryUsageBytes:
return internalQueryMaxBlockingSortMemoryUsageBytes;
};
MONGO_UNREACHABLE_TASSERT(10869600);
}
} // namespace
long long loadMemoryLimit(StageMemoryLimit stage) {
return getMemoryLimitKnob(stage).loadRelaxed();
}
void appendStageMemoryLimitsToExplain(BSONObjBuilder& bob) {
bob.appendNumber("internalQueryFacetBufferSizeBytes",
loadMemoryLimit(StageMemoryLimit::QueryFacetBufferSizeBytes));
bob.appendNumber("internalDocumentSourceGroupMaxMemoryBytes",
loadMemoryLimit(StageMemoryLimit::DocumentSourceGroupMaxMemoryBytes));
bob.appendNumber("internalQueryMaxBlockingSortMemoryUsageBytes",
loadMemoryLimit(StageMemoryLimit::QueryMaxBlockingSortMemoryUsageBytes));
bob.appendNumber(
"internalDocumentSourceSetWindowFieldsMaxMemoryBytes",
loadMemoryLimit(StageMemoryLimit::DocumentSourceSetWindowFieldsMaxMemoryBytes));
}
} // namespace mongo

View File

@ -0,0 +1,62 @@
/**
* Copyright (C) 2025-present MongoDB, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Server Side Public License, version 1,
* as published by MongoDB, Inc.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Server Side Public License for more details.
*
* You should have received a copy of the Server Side Public License
* along with this program. If not, see
* <http://www.mongodb.com/licensing/server-side-public-license>.
*
* As a special exception, the copyright holders give permission to link the
* code of portions of this program with the OpenSSL library under certain
* conditions as described in each individual source file and distribute
* linked combinations including the program with the OpenSSL library. You
* must comply with the Server Side Public License in all respects for
* all of the code used other than as permitted herein. If you modify file(s)
* with this exception, you may extend this exception to your version of the
* file(s), but you are not obligated to do so. If you do not wish to do so,
* delete this exception statement from your version. If you delete this
* exception statement from all source files in the program, then also delete
* it in the license file.
*/
#pragma once
#include "mongo/bson/bsonobjbuilder.h"
namespace mongo {
enum class StageMemoryLimit {
DocumentSourceLookupCacheSizeBytes,
DocumentSourceGraphLookupMaxMemoryBytes,
DocumentSourceGroupMaxMemoryBytes,
DocumentSourceSetWindowFieldsMaxMemoryBytes,
DocumentSourceBucketAutoMaxMemoryBytes,
DocumentSourceDensifyMaxMemoryBytes,
QueryFacetBufferSizeBytes,
TextOrStageMaxMemoryBytes,
QuerySBELookupApproxMemoryUseInBytesBeforeSpill,
QuerySBEAggApproxMemoryUseInBytesBeforeSpill,
QueryMaxSpoolMemoryUsageBytes,
QueryMaxBlockingSortMemoryUsageBytes,
};
/**
* Returns the memory limit in bytes for the given stage according to the server parameters.
*/
long long loadMemoryLimit(StageMemoryLimit stage);
/**
* Adds values of the server parameters, responsible for the memory limits, to the explain command
* output.
*/
void appendStageMemoryLimitsToExplain(BSONObjBuilder& bob);
} // namespace mongo

View File

@ -39,7 +39,7 @@ server_parameters:
will cache before abandoning the cache and executing the full pipeline on each iteration."
set_at: [startup, runtime]
cpp_varname: "internalDocumentSourceLookupCacheSizeBytes"
cpp_vartype: AtomicWord<int>
cpp_vartype: AtomicWord<long long>
default:
expr: 100 * 1024 * 1024
validator:
@ -102,7 +102,7 @@ server_parameters:
description: "Limits the number of bytes densification can use to store partition information."
set_at: [startup, runtime]
cpp_varname: "internalDocumentSourceDensifyMaxMemoryBytes"
cpp_vartype: AtomicWord<int>
cpp_vartype: AtomicWord<long long>
default:
expr: 100 * 1024 * 1024
validator:
@ -113,7 +113,7 @@ server_parameters:
description: "The number of bytes to buffer at once during a $facet stage."
set_at: [startup, runtime]
cpp_varname: "internalQueryFacetBufferSizeBytes"
cpp_vartype: AtomicWord<int>
cpp_vartype: AtomicWord<long long>
default:
expr: 100 * 1024 * 1024
validator:
@ -181,7 +181,7 @@ server_parameters:
possible to sort more data, but this limit will still constrain the memory consumption.
set_at: [startup, runtime]
cpp_varname: "internalQueryMaxBlockingSortMemoryUsageBytes"
cpp_vartype: AtomicWord<int>
cpp_vartype: AtomicWord<long long>
default:
expr: 100 * 1024 * 1024
validator:

View File

@ -92,10 +92,6 @@ extern AtomicWord<bool> internalQueryForceIntersectionPlans;
extern AtomicWord<bool> internalQueryPlannerEnableHashIntersection;
extern AtomicWord<int> internalQueryMaxBlockingSortMemoryUsageBytes;
extern AtomicWord<int> internalQueryPlanEvaluationMaxResults;
namespace cbr = cost_based_ranker;
namespace PlanRankingTests {
@ -293,20 +289,11 @@ public:
PlanRankingPreferNonFailed()
: PlanRankingTestBase(),
_internalQueryMaxBlockingSortMemoryUsageBytes(
internalQueryMaxBlockingSortMemoryUsageBytes.load()),
"internalQueryMaxBlockingSortMemoryUsageBytes", 10),
// We set the max results to decrease the amount of work that is done during the trial
// period. We want it to do less work than there are docs to ensure that no plan reaches
// EOF.
_internalQueryPlanEvaluationMaxResults(internalQueryPlanEvaluationMaxResults.load()) {
internalQueryMaxBlockingSortMemoryUsageBytes.store(10);
internalQueryPlanEvaluationMaxResults.store(100);
}
~PlanRankingPreferNonFailed() override {
internalQueryMaxBlockingSortMemoryUsageBytes.store(
_internalQueryMaxBlockingSortMemoryUsageBytes);
internalQueryPlanEvaluationMaxResults.store(_internalQueryPlanEvaluationMaxResults);
}
_internalQueryPlanEvaluationMaxResults("internalQueryPlanEvaluationMaxResults", 100) {}
void run() {
const size_t numDocs = 1000;
@ -378,10 +365,8 @@ public:
}
private:
// Holds the value of global "internalQueryMaxBlockingSortMemoryUsageBytes" setParameter flag.
// Restored at end of test invocation regardless of test result.
int _internalQueryMaxBlockingSortMemoryUsageBytes;
int _internalQueryPlanEvaluationMaxResults;
RAIIServerParameterControllerForTest _internalQueryMaxBlockingSortMemoryUsageBytes;
RAIIServerParameterControllerForTest _internalQueryPlanEvaluationMaxResults;
};
/**

View File

@ -66,7 +66,7 @@
#include "mongo/db/query/plan_executor_impl.h"
#include "mongo/db/query/plan_yield_policy.h"
#include "mongo/db/query/query_planner_params.h"
#include "mongo/db/query/query_stage_memory_limit_knobs_gen.h"
#include "mongo/db/query/stage_memory_limit_knobs/knobs.h"
#include "mongo/db/record_id.h"
#include "mongo/db/service_context.h"
#include "mongo/db/session/logical_session_id.h"
@ -322,7 +322,7 @@ public:
};
uint64_t maxMemoryUsageBytes() const {
return internalQueryMaxBlockingSortMemoryUsageBytes.load();
return loadMemoryLimit(StageMemoryLimit::QueryMaxBlockingSortMemoryUsageBytes);
}
static const char* ns() {