From 5e73f7f9e9abee0481eb29d28124b2a557dbf54a Mon Sep 17 00:00:00 2001 From: Dan Engelbrecht Date: Tue, 22 Oct 2024 12:50:30 +0200 Subject: Use a smaller thread pool during pre-cache phase of GC to reduce memory pressure (#205) --- CHANGELOG.md | 1 + src/zenstore/gc.cpp | 18 +++++++++++------- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc5b227ba..85b5f1022 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Separate page for inspecting server stats - Improvement: When batch-fetching cache values/attachments, only use block memory-buffering for items that may be memcached to reduce disk I/O - Improvement: `zen project-drop` command defaults to dry-run to prevent accidental drop and provides information on how to actually perform the drop +- Improvement: Use a smaller thread pool during pre-cache phase of GC to reduce memory pressure - Bugfix: Parse filenames as utf8 string when mirroring files inside an oplog using `zen oplog-mirror` and `zen vfs` - Bugfix: Properly initialize stats for file/jupiter/zen remote project store - fixes stats log output when exporting and importing oplogs - Cleanup: Removed GCv1 implementation diff --git a/src/zenstore/gc.cpp b/src/zenstore/gc.cpp index 981ba15cb..be8fc0148 100644 --- a/src/zenstore/gc.cpp +++ b/src/zenstore/gc.cpp @@ -632,7 +632,8 @@ GcManager::CollectGarbage(const GcSettings& Settings) std::unordered_map, GcCompactStoreStats*> StoreCompactors; RwLock StoreCompactorsLock; - WorkerThreadPool& ThreadPool = Settings.SingleThread ? GetSyncWorkerPool() : GetMediumWorkerPool(EWorkloadType::Background); + WorkerThreadPool& PreCachePhaseThreadPool = + Settings.SingleThread ? GetSyncWorkerPool() : GetSmallWorkerPool(EWorkloadType::Background); ZEN_INFO("GCV2: Removing expired data from {} referencers", m_GcReferencers.size()); if (!m_GcReferencers.empty()) @@ -662,7 +663,7 @@ GcManager::CollectGarbage(const GcSettings& Settings) GcReferencer* Owner = m_GcReferencers[Index]; std::pair* Stats = &Result.ReferencerStats[Index]; WorkLeft.AddCount(1); - ThreadPool.ScheduleWork([this, &Ctx, &WorkLeft, Owner, Stats, &StoreCompactorsLock, &StoreCompactors]() { + PreCachePhaseThreadPool.ScheduleWork([this, &Ctx, &WorkLeft, Owner, Stats, &StoreCompactorsLock, &StoreCompactors]() { auto _ = MakeGuard([&WorkLeft]() { WorkLeft.CountDown(); }); try { @@ -728,7 +729,7 @@ GcManager::CollectGarbage(const GcSettings& Settings) GcReferenceStore* ReferenceStore = m_GcReferenceStores[Index]; std::pair* Stats = &Result.ReferenceStoreStats[Index]; WorkLeft.AddCount(1); - ThreadPool.ScheduleWork( + PreCachePhaseThreadPool.ScheduleWork( [this, &Ctx, ReferenceStore, Stats, Index, &WorkLeft, &ReferencePrunersLock, &ReferencePruners]() { auto _ = MakeGuard([&WorkLeft]() { WorkLeft.CountDown(); }); try @@ -799,7 +800,7 @@ GcManager::CollectGarbage(const GcSettings& Settings) GcReferencer* Referencer = m_GcReferencers[Index]; std::pair* Stats = &Result.ReferencerStats[Index]; WorkLeft.AddCount(1); - ThreadPool.ScheduleWork( + PreCachePhaseThreadPool.ScheduleWork( [this, &Ctx, &WorkLeft, Referencer, Index, Stats, &ReferenceCheckersLock, &ReferenceCheckers]() { auto _ = MakeGuard([&WorkLeft]() { WorkLeft.CountDown(); }); // The Referencer will create a reference checker that guarantees that the references do not change as @@ -873,7 +874,7 @@ GcManager::CollectGarbage(const GcSettings& Settings) size_t Index = It.second; std::pair* Stats = &Result.ReferencerStats[Index]; WorkLeft.AddCount(1); - ThreadPool.ScheduleWork([this, &Ctx, Checker, Index, Stats, &WorkLeft]() { + PreCachePhaseThreadPool.ScheduleWork([this, &Ctx, Checker, Index, Stats, &WorkLeft]() { auto _ = MakeGuard([&WorkLeft]() { WorkLeft.CountDown(); }); try { @@ -893,6 +894,9 @@ GcManager::CollectGarbage(const GcSettings& Settings) } } + WorkerThreadPool& LockedPhaseThreadPool = + Settings.SingleThread ? GetSyncWorkerPool() : GetMediumWorkerPool(EWorkloadType::Background); + std::vector LockerScopes; SCOPED_TIMER(uint64_t ElapsedMS = Timer.GetElapsedTimeMs(); Result.WriteBlockMS = std::chrono::milliseconds(ElapsedMS); ZEN_INFO("GCV2: Writes blocked for {}", NiceTimeSpanMs(ElapsedMS))); @@ -957,7 +961,7 @@ GcManager::CollectGarbage(const GcSettings& Settings) size_t Index = It.second; std::pair* Stats = &Result.ReferencerStats[Index]; WorkLeft.AddCount(1); - ThreadPool.ScheduleWork([this, &Ctx, Checker, Index, Stats, &WorkLeft]() { + LockedPhaseThreadPool.ScheduleWork([this, &Ctx, Checker, Index, Stats, &WorkLeft]() { auto _ = MakeGuard([&WorkLeft]() { WorkLeft.CountDown(); }); try { @@ -1030,7 +1034,7 @@ GcManager::CollectGarbage(const GcSettings& Settings) size_t Index = It.first; GcReferenceStoreStats* Stats = &Result.ReferenceStoreStats[Index].second; WorkLeft.AddCount(1); - ThreadPool.ScheduleWork( + LockedPhaseThreadPool.ScheduleWork( [this, &Ctx, Pruner, Stats, &WorkLeft, &GetUnusedReferences, &StoreCompactorsLock, &StoreCompactors]() { auto _ = MakeGuard([&WorkLeft]() { WorkLeft.CountDown(); }); // Go through all the ReferenceCheckers to see if the list of Cids the collector selected are -- cgit v1.2.3