diff --git a/versioning/BRM/extentmap.cpp b/versioning/BRM/extentmap.cpp index bed1f0bce..11e72f0ef 100644 --- a/versioning/BRM/extentmap.cpp +++ b/versioning/BRM/extentmap.cpp @@ -1859,16 +1859,35 @@ void ExtentMap::save(const string& filename) throw; } - for (auto& lbidEMEntryPair : *fExtentMapRBTree) + // MCOL-5623 Prepare `ExtentMap` buffer before write. + const size_t emNumOfElements = fExtentMapRBTree->size(); + auto emIterator = fExtentMapRBTree->begin(); + size_t emIndex = 0; + while (emIndex < emNumOfElements) { - EMEntry& emEntry = lbidEMEntryPair.second; - const uint32_t writeSize = sizeof(EMEntry); - char* writePos = reinterpret_cast(&emEntry); - uint32_t progress = 0; + const size_t emNumOfElementsInBatch = std::min(EM_SAVE_NUM_PER_BATCH, emNumOfElements - emIndex); + const size_t emSizeInBatch = emNumOfElementsInBatch * sizeof(EMEntry); + std::unique_ptr extentMapBuffer(new char[emSizeInBatch]); - while (progress < writeSize) + const size_t endOfBatch = std::min(emIndex + EM_SAVE_NUM_PER_BATCH, emNumOfElements); + size_t offset = 0; + while (emIndex < endOfBatch) { - auto err = out->write(writePos + progress, writeSize - progress); + EMEntry& emEntry = emIterator->second; + const size_t writeSize = sizeof(EMEntry); + char* source = reinterpret_cast(&emEntry); + std::memcpy(&extentMapBuffer[offset], source, writeSize); + offset += writeSize; + std::advance(emIterator, 1); + ++emIndex; + } + // Double check. + idbassert(offset == emSizeInBatch); + + offset = 0; + while (offset < emSizeInBatch) + { + auto err = out->write(&extentMapBuffer[offset], emSizeInBatch - offset); if (err < 0) { releaseFreeList(READ); @@ -1876,7 +1895,7 @@ void ExtentMap::save(const string& filename) releaseEMEntryTable(READ); throw ios_base::failure("ExtentMap::save(): write failed. Check the error log."); } - progress += err; + offset += err; } } diff --git a/versioning/BRM/extentmap.h b/versioning/BRM/extentmap.h index 927405970..ab7c3f4ee 100644 --- a/versioning/BRM/extentmap.h +++ b/versioning/BRM/extentmap.h @@ -1061,6 +1061,7 @@ class ExtentMap : public Undoable static const constexpr size_t EM_INCREMENT = EM_INCREMENT_ROWS * sizeof(EMEntry); static const constexpr size_t EM_FREELIST_INITIAL_SIZE = 50 * sizeof(InlineLBIDRange); static const constexpr size_t EM_FREELIST_INCREMENT = 50 * sizeof(InlineLBIDRange); + static const constexpr size_t EM_SAVE_NUM_PER_BATCH = 1000000; // RBTree constants. static const size_t EM_RB_TREE_NODE_SIZE = sizeof(EMEntry) + 8 * sizeof(uint64_t); static const size_t EM_RB_TREE_EMPTY_SIZE = 1024;