Compare commits
5 Commits
master
...
jenniferpe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e74d2910bb | ||
|
|
280145e994 | ||
|
|
df7136e2fa | ||
|
|
36d0612419 | ||
|
|
4bd264e877 |
@ -2540,6 +2540,7 @@ if wiredtiger:
|
||||
'keypattern_test.cpp',
|
||||
'keys_collection_document_test.cpp',
|
||||
'logical_time_test.cpp',
|
||||
'memory_parameter_test.cpp',
|
||||
'mirroring_sampler_test.cpp',
|
||||
'multi_key_path_tracker_test.cpp',
|
||||
'namespace_string_test.cpp',
|
||||
@ -2589,6 +2590,7 @@ if wiredtiger:
|
||||
'$BUILD_DIR/mongo/db/change_stream_change_collection_manager',
|
||||
'$BUILD_DIR/mongo/db/change_stream_serverless_helpers',
|
||||
'$BUILD_DIR/mongo/db/change_streams_cluster_parameter',
|
||||
'$BUILD_DIR/mongo/db/memory_parameters',
|
||||
'$BUILD_DIR/mongo/db/mongohasher',
|
||||
'$BUILD_DIR/mongo/db/ops/write_ops',
|
||||
'$BUILD_DIR/mongo/db/pipeline/change_stream_expired_pre_image_remover',
|
||||
|
||||
@ -100,6 +100,7 @@ env.Library(
|
||||
LIBDEPS=[
|
||||
"$BUILD_DIR/mongo/base",
|
||||
"$BUILD_DIR/mongo/db/exec/sbe/query_sbe",
|
||||
'$BUILD_DIR/mongo/util/memory_util',
|
||||
"canonical_query",
|
||||
],
|
||||
)
|
||||
@ -257,14 +258,15 @@ env.Library(
|
||||
source=[
|
||||
'ce_mode_parameter.cpp',
|
||||
'framework_control.cpp',
|
||||
'plan_cache_size_parameter.cpp',
|
||||
'query_feature_flags.idl',
|
||||
'query_knobs.idl',
|
||||
'sbe_plan_cache_on_parameter_change.cpp',
|
||||
'telemetry_util.cpp',
|
||||
],
|
||||
LIBDEPS_PRIVATE=[
|
||||
'$BUILD_DIR/mongo/db/server_base',
|
||||
'$BUILD_DIR/mongo/db/service_context',
|
||||
'$BUILD_DIR/mongo/util/memory_util',
|
||||
'$BUILD_DIR/mongo/util/pcre_wrapper',
|
||||
],
|
||||
)
|
||||
@ -372,7 +374,6 @@ env.CppUnitTest(
|
||||
'map_reduce_output_format_test.cpp',
|
||||
"parsed_distinct_test.cpp",
|
||||
"plan_cache_indexability_test.cpp",
|
||||
"plan_cache_size_parameter_test.cpp",
|
||||
"plan_cache_key_info_test.cpp",
|
||||
"plan_cache_test.cpp",
|
||||
"plan_ranker_test.cpp",
|
||||
@ -412,6 +413,7 @@ env.CppUnitTest(
|
||||
"$BUILD_DIR/mongo/db/catalog/collection_crud",
|
||||
"$BUILD_DIR/mongo/db/concurrency/lock_manager",
|
||||
"$BUILD_DIR/mongo/db/exec/sbe/sbe_plan_stage_test",
|
||||
"$BUILD_DIR/mongo/db/memory_parameters",
|
||||
"$BUILD_DIR/mongo/db/multitenancy",
|
||||
"$BUILD_DIR/mongo/db/pipeline/aggregation_request_helper",
|
||||
"$BUILD_DIR/mongo/db/pipeline/document_source_mock",
|
||||
|
||||
@ -1,79 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2021-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/plan_cache_size_parameter.h"
|
||||
|
||||
#include "mongo/unittest/unittest.h"
|
||||
|
||||
namespace mongo::plan_cache_util {
|
||||
|
||||
bool operator==(const PlanCacheSizeParameter& lhs, const PlanCacheSizeParameter& rhs) {
|
||||
constexpr double kEpsilon = 1e-10;
|
||||
return std::abs(lhs.size - rhs.size) < kEpsilon && lhs.units == rhs.units;
|
||||
}
|
||||
|
||||
TEST(PlanCacheParameterTest, ParseUnitStringPercent) {
|
||||
ASSERT_TRUE(PlanCacheSizeUnits::kPercent == parseUnitString("%"));
|
||||
}
|
||||
|
||||
TEST(PlanCacheParameterTest, ParseUnitStringMB) {
|
||||
ASSERT_TRUE(PlanCacheSizeUnits::kMB == parseUnitString("MB"));
|
||||
ASSERT_TRUE(PlanCacheSizeUnits::kMB == parseUnitString("mb"));
|
||||
ASSERT_TRUE(PlanCacheSizeUnits::kMB == parseUnitString("mB"));
|
||||
ASSERT_TRUE(PlanCacheSizeUnits::kMB == parseUnitString("Mb"));
|
||||
}
|
||||
|
||||
TEST(PlanCacheParameterTest, ParseUnitStringGB) {
|
||||
ASSERT_TRUE(PlanCacheSizeUnits::kGB == parseUnitString("GB"));
|
||||
ASSERT_TRUE(PlanCacheSizeUnits::kGB == parseUnitString("gb"));
|
||||
ASSERT_TRUE(PlanCacheSizeUnits::kGB == parseUnitString("gB"));
|
||||
ASSERT_TRUE(PlanCacheSizeUnits::kGB == parseUnitString("Gb"));
|
||||
}
|
||||
|
||||
TEST(PlanCacheParameterTest, ParseUnitStringIncorrectValue) {
|
||||
ASSERT_NOT_OK(parseUnitString("").getStatus());
|
||||
ASSERT_NOT_OK(parseUnitString(" ").getStatus());
|
||||
ASSERT_NOT_OK(parseUnitString("KB").getStatus());
|
||||
}
|
||||
|
||||
TEST(PlanCacheParameterTest, ParsePlanCacheSizeParameter) {
|
||||
ASSERT_TRUE((PlanCacheSizeParameter{10.0, PlanCacheSizeUnits::kPercent}) ==
|
||||
PlanCacheSizeParameter::parse("10%"));
|
||||
ASSERT_TRUE((PlanCacheSizeParameter{300.0, PlanCacheSizeUnits::kMB}) ==
|
||||
PlanCacheSizeParameter::parse("300MB"));
|
||||
ASSERT_TRUE((PlanCacheSizeParameter{4.0, PlanCacheSizeUnits::kGB}) ==
|
||||
PlanCacheSizeParameter::parse("4GB"));
|
||||
ASSERT_TRUE((PlanCacheSizeParameter{5.1, PlanCacheSizeUnits::kPercent}) ==
|
||||
PlanCacheSizeParameter::parse(" 5.1%"));
|
||||
ASSERT_TRUE((PlanCacheSizeParameter{11.1, PlanCacheSizeUnits::kMB}) ==
|
||||
PlanCacheSizeParameter::parse("11.1 mb"));
|
||||
ASSERT_TRUE((PlanCacheSizeParameter{12.1, PlanCacheSizeUnits::kGB}) ==
|
||||
PlanCacheSizeParameter::parse(" 12.1 Gb "));
|
||||
}
|
||||
} // namespace mongo::plan_cache_util
|
||||
@ -30,8 +30,9 @@ global:
|
||||
cpp_namespace: "mongo"
|
||||
cpp_includes:
|
||||
- "mongo/db/query/ce_mode_parameter.h"
|
||||
- "mongo/db/query/plan_cache_size_parameter.h"
|
||||
- "mongo/util/memory_util.h"
|
||||
- "mongo/db/query/sbe_plan_cache_on_parameter_change.h"
|
||||
- "mongo/db/query/telemetry_util.h"
|
||||
- "mongo/platform/atomic_proxy.h"
|
||||
- "mongo/platform/atomic_word.h"
|
||||
|
||||
@ -938,6 +939,30 @@ server_parameters:
|
||||
default:
|
||||
expr: false
|
||||
|
||||
internalQueryConfigureTelemetrySamplingRate:
|
||||
description: "The maximum number of queries per second that are sampled for query telemetry.
|
||||
If the rate of queries goes above this number, then rate limiting will kick in, and any
|
||||
further queries will not be sampled. The default is INT_MAX, effectively meaning that all
|
||||
queries will be sampled. This can be set to 0 to turn telemetry off completely."
|
||||
set_at: [ startup, runtime ]
|
||||
cpp_varname: "queryTelemetrySamplingRate"
|
||||
cpp_vartype: AtomicWord<int>
|
||||
default: 2147483647
|
||||
|
||||
internalQueryConfigureTelemetryCacheSize:
|
||||
description: "The maximum amount of memory that the system will allocate for the query telemetry
|
||||
cache. This will accept values in either of the following formats:
|
||||
1. <number>% indicates a percentage of the physical memory available to the process. E.g.: 15%.
|
||||
2. <number>(MB|GB), indicates the amount of memory in MB or GB. E.g.: 1.5GB, 100MB.
|
||||
The default value is 5%, which means 5% of the physical memory available to the process."
|
||||
set_at: [ startup, runtime ]
|
||||
cpp_varname: "queryTelemetryCacheSize"
|
||||
cpp_vartype: synchronized_value<std::string>
|
||||
default: "5%"
|
||||
on_update: telemetry_util::onTelemetryCacheSizeUpdate
|
||||
validator:
|
||||
callback: telemetry_util::validateTelemetryCacheSize
|
||||
|
||||
internalQueryDisableExclusionProjectionFastPath:
|
||||
description: "If true, then ExclusionProjectionExecutor won't use fast path implementation. This
|
||||
is needed to pass generational fuzzers that are sensitive to field order and other corner cases
|
||||
|
||||
@ -30,9 +30,9 @@
|
||||
|
||||
#include "mongo/db/query/sbe_plan_cache.h"
|
||||
|
||||
#include "mongo/db/query/plan_cache_size_parameter.h"
|
||||
#include "mongo/db/server_options.h"
|
||||
#include "mongo/logv2/log.h"
|
||||
#include "mongo/util/memory_util.h"
|
||||
#include "mongo/util/processinfo.h"
|
||||
|
||||
#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kQuery
|
||||
@ -44,19 +44,19 @@ namespace {
|
||||
const auto sbePlanCacheDecoration =
|
||||
ServiceContext::declareDecoration<std::unique_ptr<sbe::PlanCache>>();
|
||||
|
||||
size_t convertToSizeInBytes(const plan_cache_util::PlanCacheSizeParameter& param) {
|
||||
size_t convertToSizeInBytes(const memory_util::MemorySize& param) {
|
||||
constexpr size_t kBytesInMB = 1024 * 1024;
|
||||
constexpr size_t kMBytesInGB = 1024;
|
||||
|
||||
double sizeInMB = param.size;
|
||||
|
||||
switch (param.units) {
|
||||
case plan_cache_util::PlanCacheSizeUnits::kPercent:
|
||||
case memory_util::MemoryUnits::kPercent:
|
||||
sizeInMB *= ProcessInfo::getMemSizeMB() / 100.0;
|
||||
break;
|
||||
case plan_cache_util::PlanCacheSizeUnits::kMB:
|
||||
case memory_util::MemoryUnits::kMB:
|
||||
break;
|
||||
case plan_cache_util::PlanCacheSizeUnits::kGB:
|
||||
case memory_util::MemoryUnits::kGB:
|
||||
sizeInMB *= kMBytesInGB;
|
||||
break;
|
||||
}
|
||||
@ -75,8 +75,7 @@ size_t capPlanCacheSize(size_t planCacheSize) {
|
||||
constexpr size_t kMaximumPlanCacheSize = 500 * kBytesInGB;
|
||||
|
||||
// Maximum size of the plan cache expressed as a share of the memory available to the process.
|
||||
const plan_cache_util::PlanCacheSizeParameter limitToProcessSize{
|
||||
25, plan_cache_util::PlanCacheSizeUnits::kPercent};
|
||||
const memory_util::MemorySize limitToProcessSize{25, memory_util::MemoryUnits::kPercent};
|
||||
const size_t limitToProcessSizeInBytes = convertToSizeInBytes(limitToProcessSize);
|
||||
|
||||
// The size will be capped by the minimum of the two values defined above.
|
||||
@ -93,7 +92,7 @@ size_t capPlanCacheSize(size_t planCacheSize) {
|
||||
return planCacheSize;
|
||||
}
|
||||
|
||||
size_t getPlanCacheSizeInBytes(const plan_cache_util::PlanCacheSizeParameter& param) {
|
||||
size_t getPlanCacheSizeInBytes(const memory_util::MemorySize& param) {
|
||||
size_t planCacheSize = convertToSizeInBytes(param);
|
||||
uassert(5968001,
|
||||
"Cache size must be at least 1KB * number of cores",
|
||||
@ -103,8 +102,7 @@ size_t getPlanCacheSizeInBytes(const plan_cache_util::PlanCacheSizeParameter& pa
|
||||
|
||||
class PlanCacheOnParamChangeUpdaterImpl final : public plan_cache_util::OnParamChangeUpdater {
|
||||
public:
|
||||
void updateCacheSize(ServiceContext* serviceCtx,
|
||||
plan_cache_util::PlanCacheSizeParameter parameter) final {
|
||||
void updateCacheSize(ServiceContext* serviceCtx, memory_util::MemorySize parameter) final {
|
||||
if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) {
|
||||
auto size = getPlanCacheSizeInBytes(parameter);
|
||||
auto& globalPlanCache = sbePlanCacheDecoration(serviceCtx);
|
||||
@ -126,7 +124,7 @@ ServiceContext::ConstructorActionRegisterer planCacheRegisterer{
|
||||
std::make_unique<PlanCacheOnParamChangeUpdaterImpl>();
|
||||
|
||||
if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) {
|
||||
auto status = plan_cache_util::PlanCacheSizeParameter::parse(planCacheSize.get());
|
||||
auto status = memory_util::MemorySize::parse(planCacheSize.get());
|
||||
uassertStatusOK(status);
|
||||
|
||||
auto size = getPlanCacheSizeInBytes(status.getValue());
|
||||
|
||||
@ -56,7 +56,7 @@ Status clearSbeCacheOnParameterChangeHelper() {
|
||||
}
|
||||
|
||||
Status onPlanCacheSizeUpdate(const std::string& str) {
|
||||
auto newSize = PlanCacheSizeParameter::parse(str);
|
||||
auto newSize = memory_util::MemorySize::parse(str);
|
||||
if (!newSize.isOK()) {
|
||||
return newSize.getStatus();
|
||||
}
|
||||
@ -73,7 +73,7 @@ Status onPlanCacheSizeUpdate(const std::string& str) {
|
||||
}
|
||||
|
||||
Status validatePlanCacheSize(const std::string& str, const boost::optional<TenantId>&) {
|
||||
return PlanCacheSizeParameter::parse(str).getStatus();
|
||||
return memory_util::MemorySize::parse(str).getStatus();
|
||||
}
|
||||
|
||||
const Decorable<ServiceContext>::Decoration<std::unique_ptr<OnParamChangeUpdater>>
|
||||
|
||||
@ -32,8 +32,8 @@
|
||||
#include <string>
|
||||
|
||||
#include "mongo/base/status.h"
|
||||
#include "mongo/db/query/plan_cache_size_parameter.h"
|
||||
#include "mongo/db/service_context.h"
|
||||
#include "mongo/util/memory_util.h"
|
||||
|
||||
namespace mongo::plan_cache_util {
|
||||
|
||||
@ -70,11 +70,12 @@ public:
|
||||
virtual ~OnParamChangeUpdater() = default;
|
||||
|
||||
/**
|
||||
* Resizes the SBE plan cache decorating 'serviceCtx' to the new size given by 'parameter'. If
|
||||
* Resizes the SBE plan cache decorating 'serviceCtx' to the new size given by 'memorySize'. If
|
||||
* the new cache size is smaller than the old, cache entries are evicted in order to ensure the
|
||||
* cache fits within the new size bound.
|
||||
*/
|
||||
virtual void updateCacheSize(ServiceContext* serviceCtx, PlanCacheSizeParameter parameter) = 0;
|
||||
virtual void updateCacheSize(ServiceContext* serviceCtx,
|
||||
memory_util::MemorySize memorySize) = 0;
|
||||
|
||||
/**
|
||||
* Deletes all plans from the SBE plan cache decorating 'serviceCtx'.
|
||||
|
||||
52
src/mongo/db/query/telemetry_util.cpp
Normal file
52
src/mongo/db/query/telemetry_util.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Copyright (C) 2022-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/telemetry_util.h"
|
||||
#include "mongo/util/memory_util.h"
|
||||
|
||||
namespace mongo {
|
||||
namespace telemetry_util {
|
||||
|
||||
Status onTelemetryCacheSizeUpdate(const std::string& str) {
|
||||
auto newSize = memory_util::MemorySize::parse(str);
|
||||
if (!newSize.isOK()) {
|
||||
return newSize.getStatus();
|
||||
}
|
||||
|
||||
// TODO update telemetry cache size wherever it is stored
|
||||
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status validateTelemetryCacheSize(const std::string& str, const boost::optional<TenantId>&) {
|
||||
return memory_util::MemorySize::parse(str).getStatus();
|
||||
}
|
||||
|
||||
} // namespace telemetry_util
|
||||
} // namespace mongo
|
||||
50
src/mongo/db/query/telemetry_util.h
Normal file
50
src/mongo/db/query/telemetry_util.h
Normal file
@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Copyright (C) 2022-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/base/status.h"
|
||||
#include "mongo/db/service_context.h"
|
||||
|
||||
namespace mongo {
|
||||
|
||||
namespace telemetry_util {
|
||||
|
||||
/**
|
||||
* Callback called on a change of telemetryCacheSize parameter.
|
||||
*/
|
||||
Status onTelemetryCacheSizeUpdate(const std::string& str);
|
||||
|
||||
/**
|
||||
* Callback called on validation of telemetryCacheSize parameter.
|
||||
*/
|
||||
Status validateTelemetryCacheSize(const std::string& str, const boost::optional<TenantId>&);
|
||||
|
||||
} // namespace telemetry_util
|
||||
} // namespace mongo
|
||||
@ -614,6 +614,17 @@ env.Library(
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
env.Library(
|
||||
target='memory_util',
|
||||
source=[
|
||||
'memory_util.cpp',
|
||||
],
|
||||
LIBDEPS=[
|
||||
'pcre_wrapper',
|
||||
],
|
||||
)
|
||||
|
||||
env.Benchmark(
|
||||
target='hash_table_bm',
|
||||
source='hash_table_bm.cpp',
|
||||
@ -748,6 +759,7 @@ icuEnv.CppUnitTest(
|
||||
'lru_cache_test.cpp',
|
||||
'md5_test.cpp',
|
||||
'md5main.cpp',
|
||||
'memory_util_test.cpp',
|
||||
'optional_util_test.cpp',
|
||||
'out_of_line_executor_test.cpp',
|
||||
'overloaded_visitor_test.cpp',
|
||||
@ -795,6 +807,7 @@ icuEnv.CppUnitTest(
|
||||
'icu',
|
||||
'latch_analyzer' if get_option('use-diagnostic-latches') == 'on' else [],
|
||||
'md5',
|
||||
'memory_util',
|
||||
'pcre_util',
|
||||
'pcre_wrapper',
|
||||
'periodic_runner_impl',
|
||||
|
||||
@ -27,30 +27,29 @@
|
||||
* it in the license file.
|
||||
*/
|
||||
|
||||
#include "mongo/db/query/plan_cache_size_parameter.h"
|
||||
#include "mongo/util/memory_util.h"
|
||||
|
||||
#include "mongo/db/query/query_knobs_gen.h"
|
||||
#include "mongo/util/pcre.h"
|
||||
|
||||
namespace mongo::plan_cache_util {
|
||||
namespace mongo::memory_util {
|
||||
|
||||
StatusWith<PlanCacheSizeUnits> parseUnitString(const std::string& strUnit) {
|
||||
StatusWith<MemoryUnits> parseUnitString(const std::string& strUnit) {
|
||||
if (strUnit.empty()) {
|
||||
return Status(ErrorCodes::Error{6007010}, "Unit value cannot be empty");
|
||||
}
|
||||
|
||||
if (strUnit[0] == '%') {
|
||||
return PlanCacheSizeUnits::kPercent;
|
||||
return MemoryUnits::kPercent;
|
||||
} else if (strUnit[0] == 'M' || strUnit[0] == 'm') {
|
||||
return PlanCacheSizeUnits::kMB;
|
||||
return MemoryUnits::kMB;
|
||||
} else if (strUnit[0] == 'G' || strUnit[0] == 'g') {
|
||||
return PlanCacheSizeUnits::kGB;
|
||||
return MemoryUnits::kGB;
|
||||
}
|
||||
|
||||
return Status(ErrorCodes::Error{6007011}, "Incorrect unit value");
|
||||
}
|
||||
|
||||
StatusWith<PlanCacheSizeParameter> PlanCacheSizeParameter::parse(const std::string& str) {
|
||||
StatusWith<MemorySize> MemorySize::parse(const std::string& str) {
|
||||
// Looks for a floating point number with followed by a unit suffix (MB, GB, %).
|
||||
static auto& re = *new pcre::Regex(R"re((?i)^\s*(\d+\.?\d*)\s*(MB|GB|%)\s*$)re");
|
||||
auto m = re.matchView(str);
|
||||
@ -65,7 +64,7 @@ StatusWith<PlanCacheSizeParameter> PlanCacheSizeParameter::parse(const std::stri
|
||||
return statusWithUnit.getStatus();
|
||||
}
|
||||
|
||||
return PlanCacheSizeParameter{size, statusWithUnit.getValue()};
|
||||
return MemorySize{size, statusWithUnit.getValue()};
|
||||
}
|
||||
|
||||
} // namespace mongo::plan_cache_util
|
||||
} // namespace mongo::memory_util
|
||||
70
src/mongo/util/memory_util.cpp
Normal file
70
src/mongo/util/memory_util.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Copyright (C) 2021-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/util/memory_util.h"
|
||||
|
||||
#include "mongo/util/pcre.h"
|
||||
|
||||
namespace mongo::memory_util {
|
||||
|
||||
StatusWith<MemoryUnits> parseUnitString(const std::string& strUnit) {
|
||||
if (strUnit.empty()) {
|
||||
return Status(ErrorCodes::Error{6007010}, "Unit value cannot be empty");
|
||||
}
|
||||
|
||||
if (strUnit[0] == '%') {
|
||||
return MemoryUnits::kPercent;
|
||||
} else if (strUnit[0] == 'M' || strUnit[0] == 'm') {
|
||||
return MemoryUnits::kMB;
|
||||
} else if (strUnit[0] == 'G' || strUnit[0] == 'g') {
|
||||
return MemoryUnits::kGB;
|
||||
}
|
||||
|
||||
return Status(ErrorCodes::Error{6007011}, "Incorrect unit value");
|
||||
}
|
||||
|
||||
StatusWith<MemorySize> MemorySize::parse(const std::string& str) {
|
||||
// Looks for a floating point number with followed by a unit suffix (MB, GB, %).
|
||||
static auto& re = *new pcre::Regex(R"re((?i)^\s*(\d+\.?\d*)\s*(MB|GB|%)\s*$)re");
|
||||
auto m = re.matchView(str);
|
||||
if (!m) {
|
||||
return {ErrorCodes::Error{6007012}, "Unable to parse plan cache size string"};
|
||||
}
|
||||
double size = std::stod(std::string{m[1]});
|
||||
std::string strUnit{m[2]};
|
||||
|
||||
auto statusWithUnit = parseUnitString(strUnit);
|
||||
if (!statusWithUnit.isOK()) {
|
||||
return statusWithUnit.getStatus();
|
||||
}
|
||||
|
||||
return MemorySize{size, statusWithUnit.getValue()};
|
||||
}
|
||||
|
||||
} // namespace mongo::memory_util
|
||||
@ -33,27 +33,27 @@
|
||||
|
||||
#include "mongo/base/status_with.h"
|
||||
|
||||
namespace mongo::plan_cache_util {
|
||||
namespace mongo::memory_util {
|
||||
|
||||
/**
|
||||
* Defines units of planCacheSize parameter.
|
||||
* Defines units of memory consumption.
|
||||
*/
|
||||
enum class PlanCacheSizeUnits {
|
||||
enum class MemoryUnits {
|
||||
kPercent,
|
||||
kMB,
|
||||
kGB,
|
||||
};
|
||||
|
||||
StatusWith<PlanCacheSizeUnits> parseUnitString(const std::string& strUnit);
|
||||
StatusWith<MemoryUnits> parseUnitString(const std::string& strUnit);
|
||||
|
||||
/**
|
||||
* Represents parsed planCacheSize parameter.
|
||||
* Represents parsed memory size parameter.
|
||||
*/
|
||||
struct PlanCacheSizeParameter {
|
||||
static StatusWith<PlanCacheSizeParameter> parse(const std::string& str);
|
||||
struct MemorySize {
|
||||
static StatusWith<MemorySize> parse(const std::string& str);
|
||||
|
||||
const double size;
|
||||
const PlanCacheSizeUnits units;
|
||||
const MemoryUnits units;
|
||||
};
|
||||
|
||||
} // namespace mongo::plan_cache_util
|
||||
} // namespace mongo::memory_util
|
||||
73
src/mongo/util/memory_util_test.cpp
Normal file
73
src/mongo/util/memory_util_test.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Copyright (C) 2021-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/util/memory_util.h"
|
||||
|
||||
#include "mongo/unittest/unittest.h"
|
||||
|
||||
namespace mongo::memory_util {
|
||||
|
||||
bool operator==(const MemorySize& lhs, const MemorySize& rhs) {
|
||||
constexpr double kEpsilon = 1e-10;
|
||||
return std::abs(lhs.size - rhs.size) < kEpsilon && lhs.units == rhs.units;
|
||||
}
|
||||
|
||||
TEST(MemorySizeTest, ParseUnitStringPercent) {
|
||||
ASSERT_TRUE(MemoryUnits::kPercent == parseUnitString("%"));
|
||||
}
|
||||
|
||||
TEST(MemorySizeTest, ParseUnitStringMB) {
|
||||
ASSERT_TRUE(MemoryUnits::kMB == parseUnitString("MB"));
|
||||
ASSERT_TRUE(MemoryUnits::kMB == parseUnitString("mb"));
|
||||
ASSERT_TRUE(MemoryUnits::kMB == parseUnitString("mB"));
|
||||
ASSERT_TRUE(MemoryUnits::kMB == parseUnitString("Mb"));
|
||||
}
|
||||
|
||||
TEST(MemorySizeTest, ParseUnitStringGB) {
|
||||
ASSERT_TRUE(MemoryUnits::kGB == parseUnitString("GB"));
|
||||
ASSERT_TRUE(MemoryUnits::kGB == parseUnitString("gb"));
|
||||
ASSERT_TRUE(MemoryUnits::kGB == parseUnitString("gB"));
|
||||
ASSERT_TRUE(MemoryUnits::kGB == parseUnitString("Gb"));
|
||||
}
|
||||
|
||||
TEST(MemorySizeTest, ParseUnitStringIncorrectValue) {
|
||||
ASSERT_NOT_OK(parseUnitString("").getStatus());
|
||||
ASSERT_NOT_OK(parseUnitString(" ").getStatus());
|
||||
ASSERT_NOT_OK(parseUnitString("KB").getStatus());
|
||||
}
|
||||
|
||||
TEST(MemorySizeTest, ParseMemorySize) {
|
||||
ASSERT_TRUE((MemorySize{10.0, MemoryUnits::kPercent}) == MemorySize::parse("10%"));
|
||||
ASSERT_TRUE((MemorySize{300.0, MemoryUnits::kMB}) == MemorySize::parse("300MB"));
|
||||
ASSERT_TRUE((MemorySize{4.0, MemoryUnits::kGB}) == MemorySize::parse("4GB"));
|
||||
ASSERT_TRUE((MemorySize{5.1, MemoryUnits::kPercent}) == MemorySize::parse(" 5.1%"));
|
||||
ASSERT_TRUE((MemorySize{11.1, MemoryUnits::kMB}) == MemorySize::parse("11.1 mb"));
|
||||
ASSERT_TRUE((MemorySize{12.1, MemoryUnits::kGB}) == MemorySize::parse(" 12.1 Gb "));
|
||||
}
|
||||
} // namespace mongo::memory_util
|
||||
Loading…
Reference in New Issue
Block a user