summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/db/catalog/index_create.cpp35
-rw-r--r--src/mongo/db/index/index_access_method.cpp10
-rw-r--r--src/mongo/db/index/index_access_method.h9
3 files changed, 46 insertions, 8 deletions
diff --git a/src/mongo/db/catalog/index_create.cpp b/src/mongo/db/catalog/index_create.cpp
index 823dacff550..b9ca4f87a3f 100644
--- a/src/mongo/db/catalog/index_create.cpp
+++ b/src/mongo/db/catalog/index_create.cpp
@@ -47,6 +47,7 @@
#include "mongo/db/operation_context.h"
#include "mongo/db/query/internal_plans.h"
#include "mongo/db/repl/replication_coordinator_global.h"
+#include "mongo/db/server_parameters.h"
#include "mongo/stdx/mutex.h"
#include "mongo/util/fail_point.h"
#include "mongo/util/fail_point_service.h"
@@ -65,6 +66,30 @@ MONGO_FP_DECLARE(crashAfterStartingIndexBuild);
MONGO_FP_DECLARE(hangAfterStartingIndexBuild);
MONGO_FP_DECLARE(hangAfterStartingIndexBuildUnlocked);
+std::atomic<std::int32_t> maxIndexBuildMemoryUsageMegabytes(500); // NOLINT
+
+class ExportedMaxIndexBuildMemoryUsageParameter
+ : public ExportedServerParameter<std::int32_t, ServerParameterType::kStartupAndRuntime> {
+public:
+ ExportedMaxIndexBuildMemoryUsageParameter()
+ : ExportedServerParameter<std::int32_t, ServerParameterType::kStartupAndRuntime>(
+ ServerParameterSet::getGlobal(),
+ "maxIndexBuildMemoryUsageMegabytes",
+ &maxIndexBuildMemoryUsageMegabytes) {}
+
+ virtual Status validate(const std::int32_t& potentialNewValue) {
+ if (potentialNewValue < 100) {
+ return Status(
+ ErrorCodes::BadValue,
+ "maxIndexBuildMemoryUsageMegabytes must be greater than or equal to 100 MB");
+ }
+
+ return Status::OK();
+ }
+
+} exportedMaxIndexBuildMemoryUsageParameter;
+
+
/**
* On rollback sets MultiIndexBlock::_needToCleanup to true.
*/
@@ -185,6 +210,11 @@ StatusWith<std::vector<BSONObj>> MultiIndexBlock::init(const std::vector<BSONObj
std::vector<BSONObj> indexInfoObjs;
indexInfoObjs.reserve(indexSpecs.size());
+ std::size_t eachIndexBuildMaxMemoryUsageBytes = 0;
+ if (!indexSpecs.empty()) {
+ eachIndexBuildMaxMemoryUsageBytes =
+ std::size_t(maxIndexBuildMemoryUsageMegabytes) * 1024 * 1024 / indexSpecs.size();
+ }
for (size_t i = 0; i < indexSpecs.size(); i++) {
BSONObj info = indexSpecs[i];
@@ -210,7 +240,7 @@ StatusWith<std::vector<BSONObj>> MultiIndexBlock::init(const std::vector<BSONObj
if (!_buildInBackground) {
// Bulk build process requires foreground building as it assumes nothing is changing
// under it.
- index.bulk = index.real->initiateBulk();
+ index.bulk = index.real->initiateBulk(eachIndexBuildMaxMemoryUsageBytes);
}
const IndexDescriptor* descriptor = index.block->getEntry()->descriptor();
@@ -221,7 +251,8 @@ StatusWith<std::vector<BSONObj>> MultiIndexBlock::init(const std::vector<BSONObj
log() << "build index on: " << ns << " properties: " << descriptor->toString();
if (index.bulk)
- log() << "\t building index using bulk method";
+ log() << "\t building index using bulk method; build may temporarily use up to "
+ << eachIndexBuildMaxMemoryUsageBytes / 1024 / 1024 << " megabytes of RAM";
index.filterExpression = index.block->getEntry()->getFilterExpression();
diff --git a/src/mongo/db/index/index_access_method.cpp b/src/mongo/db/index/index_access_method.cpp
index a4268c12055..9ca00a16f3e 100644
--- a/src/mongo/db/index/index_access_method.cpp
+++ b/src/mongo/db/index/index_access_method.cpp
@@ -402,17 +402,19 @@ Status IndexAccessMethod::compact(OperationContext* txn) {
return this->_newInterface->compact(txn);
}
-std::unique_ptr<IndexAccessMethod::BulkBuilder> IndexAccessMethod::initiateBulk() {
- return std::unique_ptr<BulkBuilder>(new BulkBuilder(this, _descriptor));
+std::unique_ptr<IndexAccessMethod::BulkBuilder> IndexAccessMethod::initiateBulk(
+ size_t maxMemoryUsageBytes) {
+ return std::unique_ptr<BulkBuilder>(new BulkBuilder(this, _descriptor, maxMemoryUsageBytes));
}
IndexAccessMethod::BulkBuilder::BulkBuilder(const IndexAccessMethod* index,
- const IndexDescriptor* descriptor)
+ const IndexDescriptor* descriptor,
+ size_t maxMemoryUsageBytes)
: _sorter(Sorter::make(
SortOptions()
.TempDir(storageGlobalParams.dbpath + "/_tmp")
.ExtSortAllowed()
- .MaxMemoryUsageBytes(100 * 1024 * 1024),
+ .MaxMemoryUsageBytes(maxMemoryUsageBytes),
BtreeExternalSortComparison(descriptor->keyPattern(), descriptor->version()))),
_real(index) {}
diff --git a/src/mongo/db/index/index_access_method.h b/src/mongo/db/index/index_access_method.h
index b3647ed3a09..7847baf4ecb 100644
--- a/src/mongo/db/index/index_access_method.h
+++ b/src/mongo/db/index/index_access_method.h
@@ -212,7 +212,9 @@ public:
using Sorter = mongo::Sorter<BSONObj, RecordId>;
- BulkBuilder(const IndexAccessMethod* index, const IndexDescriptor* descriptor);
+ BulkBuilder(const IndexAccessMethod* index,
+ const IndexDescriptor* descriptor,
+ size_t maxMemoryUsageBytes);
std::unique_ptr<Sorter> _sorter;
const IndexAccessMethod* _real;
@@ -233,8 +235,11 @@ public:
* This can return NULL, meaning bulk mode is not available.
*
* It is only legal to initiate bulk when the index is new and empty.
+ *
+ * maxMemoryUsageBytes: amount of memory consumed before the external sorter starts spilling to
+ * disk
*/
- std::unique_ptr<BulkBuilder> initiateBulk();
+ std::unique_ptr<BulkBuilder> initiateBulk(size_t maxMemoryUsageBytes);
/**
* Call this when you are ready to finish your bulk work.