diff options
author | Geir Storli <geirst@yahoo-inc.com> | 2017-05-12 11:17:32 +0000 |
---|---|---|
committer | Geir Storli <geirst@yahoo-inc.com> | 2017-05-12 14:01:25 +0000 |
commit | 90c765974b2d18b70e99a50c14244c5bc0df48d6 (patch) | |
tree | eb61663a5b14920aca87774ab6860c17472604e0 /searchlib | |
parent | 473d687fa9c4e72bc8a804fdfcf45c8cc3c789f8 (diff) |
Add support for shrinking lid space in LogDataStore.
Diffstat (limited to 'searchlib')
5 files changed, 76 insertions, 16 deletions
diff --git a/searchlib/src/tests/docstore/logdatastore/logdatastore_test.cpp b/searchlib/src/tests/docstore/logdatastore/logdatastore_test.cpp index 54218d5c73f..761d32224f5 100644 --- a/searchlib/src/tests/docstore/logdatastore/logdatastore_test.cpp +++ b/searchlib/src/tests/docstore/logdatastore/logdatastore_test.cpp @@ -765,7 +765,7 @@ struct Fixture { return serialNum++; } - Fixture(const vespalib::string &dirName, + Fixture(const vespalib::string &dirName = "tmp", bool dirCleanup = true, size_t maxFileSize = 4096 * 2) : executor(1, 0x10000), @@ -803,6 +803,10 @@ struct Fixture { } } } + void compactLidSpace(uint32_t wantedDocIdLimit) { + store.compactLidSpace(wantedDocIdLimit); + assertDocIdLimit(wantedDocIdLimit); + } void assertDocIdLimit(uint32_t expDocIdLimit) { EXPECT_EQUAL(expDocIdLimit, store.getDocIdLimit()); } @@ -881,8 +885,7 @@ TEST("require that lid space can be compacted and entries from old files skipped TEST_DO(f.assertContent({10,100,101,102,20,200,201,202,30}, 203)); f.assertDocIdLimit(203); - f.store.compactLidSpace(100); - f.assertDocIdLimit(100); + f.compactLidSpace(100); TEST_DO(f.assertContent({10,20,30}, 203)); f.writeUntilNewChunk(31); @@ -898,7 +901,7 @@ TEST("require that lid space can be compacted and entries from old files skipped } } -TEST_F("require that getLid() is protected by docIdLimit", Fixture("tmp")) +TEST_F("require that getLid() is protected by docIdLimit", Fixture) { f.write(1); vespalib::GenerationHandler::Guard guard = f.store.getLidReadGuard(); @@ -906,6 +909,45 @@ TEST_F("require that getLid() is protected by docIdLimit", Fixture("tmp")) EXPECT_FALSE(f.store.getLid(guard, 2).valid()); } +TEST_F("require that lid space can be compacted and shrunk", Fixture) +{ + f.write(1).write(2); + EXPECT_FALSE(f.store.canShrinkLidSpace()); + + f.compactLidSpace(2); + MemoryUsage before = f.store.getMemoryUsage(); + EXPECT_TRUE(f.store.canShrinkLidSpace()); + f.store.shrinkLidSpace(); + + MemoryUsage after = f.store.getMemoryUsage(); + EXPECT_LESS(after.usedBytes(), before.usedBytes()); +} + +TEST_F("require that lid space can be increased after being compacted and then shrunk", Fixture) +{ + f.write(1).write(3); + TEST_DO(f.compactLidSpace(2)); + f.write(2); + TEST_DO(f.assertDocIdLimit(3)); + f.store.shrinkLidSpace(); + TEST_DO(f.assertDocIdLimit(3)); + TEST_DO(f.assertContent({1,2}, 3)); +} + +TEST_F("require that lid space can be shrunk only after read guards are deleted", Fixture) +{ + f.write(1).write(2); + EXPECT_FALSE(f.store.canShrinkLidSpace()); + { + vespalib::GenerationHandler::Guard guard = f.store.getLidReadGuard(); + f.compactLidSpace(2); + f.write(1); // trigger remove of old generations + EXPECT_FALSE(f.store.canShrinkLidSpace()); + } + f.write(1); // trigger remove of old generations + EXPECT_TRUE(f.store.canShrinkLidSpace()); +} + TEST_MAIN() { DummyFileHeaderContext::setCreator("logdatastore_test"); TEST_RUN_ALL(); diff --git a/searchlib/src/vespa/searchlib/common/rcuvector.h b/searchlib/src/vespa/searchlib/common/rcuvector.h index bde7fb2accb..aeaec9b1022 100644 --- a/searchlib/src/vespa/searchlib/common/rcuvector.h +++ b/searchlib/src/vespa/searchlib/common/rcuvector.h @@ -58,7 +58,7 @@ private: } void expand(size_t newCapacity); void expandAndInsert(const T & v); - virtual void onExpand(); + virtual void onReallocation(); public: using ValueType = T; @@ -133,7 +133,7 @@ private: generation_t _generation; GenerationHolder _genHolderStore; - void onExpand() override; + void onReallocation() override; public: RcuVector(); diff --git a/searchlib/src/vespa/searchlib/common/rcuvector.hpp b/searchlib/src/vespa/searchlib/common/rcuvector.hpp index c68016dea81..9424331d014 100644 --- a/searchlib/src/vespa/searchlib/common/rcuvector.hpp +++ b/searchlib/src/vespa/searchlib/common/rcuvector.hpp @@ -60,7 +60,7 @@ RcuVectorBase<T>::expand(size_t newCapacity) { size_t holdSize = tmpData->capacity() * sizeof(T); vespalib::GenerationHeldBase::UP hold(new RcuVectorHeld<Array>(holdSize, std::move(tmpData))); _genHolder.hold(std::move(hold)); - onExpand(); + onReallocation(); } template <typename T> @@ -95,6 +95,7 @@ RcuVectorBase<T>::shrink(size_t newSize) size_t holdSize = tmpData->capacity() * sizeof(T); vespalib::GenerationHeldBase::UP hold(new RcuVectorHeld<Array>(holdSize, std::move(tmpData))); _genHolder.hold(std::move(hold)); + onReallocation(); } } @@ -144,11 +145,11 @@ RcuVectorBase<T>::getMemoryUsage() const template <typename T> void -RcuVectorBase<T>::onExpand() { } +RcuVectorBase<T>::onReallocation() { } template <typename T> void -RcuVector<T>::onExpand() { +RcuVector<T>::onReallocation() { _genHolderStore.transferHoldLists(_generation); } diff --git a/searchlib/src/vespa/searchlib/docstore/logdatastore.cpp b/searchlib/src/vespa/searchlib/docstore/logdatastore.cpp index 245f0ea912b..159c9882d31 100644 --- a/searchlib/src/vespa/searchlib/docstore/logdatastore.cpp +++ b/searchlib/src/vespa/searchlib/docstore/logdatastore.cpp @@ -54,7 +54,8 @@ LogDataStore::LogDataStore(vespalib::ThreadExecutor &executor, _initFlushSyncToken(0), _tlSyncer(tlSyncer), _bucketizer(bucketizer), - _currentlyCompacting() + _currentlyCompacting(), + _compactLidSpaceGeneration() { // Reserve space for 1TB summary in order to avoid locking. _fileChunks.reserve(LidInfo::getFileIdLimit()); @@ -886,15 +887,21 @@ LogDataStore::setLid(const LockGuard &guard, uint32_t lid, const LidInfo &meta) } } else { _lidInfo.ensure_size(lid+1, LidInfo()); - _lidInfo.setGeneration(_genHandler.getNextGeneration()); - _genHandler.incGeneration(); - _genHandler.updateFirstUsedGeneration(); - _lidInfo.removeOldGenerations(_genHandler.getFirstUsedGeneration()); - updateDocIdLimit(_lidInfo.size()); + incGeneration(); } + updateDocIdLimit(lid + 1); _lidInfo[lid] = meta; } +void +LogDataStore::incGeneration() +{ + _lidInfo.setGeneration(_genHandler.getNextGeneration()); + _genHandler.incGeneration(); + _genHandler.updateFirstUsedGeneration(); + _lidInfo.removeOldGenerations(_genHandler.getFirstUsedGeneration()); +} + size_t LogDataStore::computeNumberOfSignificantBucketIdBits(const IBucketizer & bucketizer, FileId fileId) const { @@ -1119,21 +1126,29 @@ void LogDataStore::compactLidSpace(uint32_t wantedDocLidLimit) { LockGuard guard(_updateLock); + assert(wantedDocLidLimit <= getDocIdLimit()); for (size_t i = wantedDocLidLimit; i < _lidInfo.size(); ++i) { _lidInfo[i] = LidInfo(); } setDocIdLimit(wantedDocLidLimit); + _compactLidSpaceGeneration = _genHandler.getCurrentGeneration(); + incGeneration(); } bool LogDataStore::canShrinkLidSpace() const { - return false; + return getDocIdLimit() < _lidInfo.size() && + _compactLidSpaceGeneration < _genHandler.getFirstUsedGeneration(); } void LogDataStore::shrinkLidSpace() { + assert(canShrinkLidSpace()); + LockGuard guard(_updateLock); + _lidInfo.shrink(getDocIdLimit()); + incGeneration(); } } // namespace search diff --git a/searchlib/src/vespa/searchlib/docstore/logdatastore.h b/searchlib/src/vespa/searchlib/docstore/logdatastore.h index 037cac58fae..c426d9bb46c 100644 --- a/searchlib/src/vespa/searchlib/docstore/logdatastore.h +++ b/searchlib/src/vespa/searchlib/docstore/logdatastore.h @@ -304,6 +304,7 @@ private: } bool shouldCompactToActiveFile(size_t compactedSize) const; std::pair<bool, FileId> findNextToCompact(); + void incGeneration(); typedef std::vector<FileId> FileIdxVector; Config _config; @@ -322,6 +323,7 @@ private: transactionlog::SyncProxy &_tlSyncer; IBucketizer::SP _bucketizer; NameIdSet _currentlyCompacting; + uint64_t _compactLidSpaceGeneration; }; } // namespace search |