diff options
| author | Dan Engelbrecht <[email protected]> | 2023-10-24 14:54:26 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-10-24 14:54:26 +0200 |
| commit | 1a144212278aa7158d6b32b63e398db95a7ae868 (patch) | |
| tree | 58735827b0b706368a82bcaaa8aaa68f211e1d10 /src/zenserver/cache/structuredcachestore.cpp | |
| parent | chunking moved to zenstore (#490) (diff) | |
| download | zen-1a144212278aa7158d6b32b63e398db95a7ae868.tar.xz zen-1a144212278aa7158d6b32b63e398db95a7ae868.zip | |
merge disk and memory layers (#493)
- Feature: Added `--cache-memlayer-sizethreshold` option to zenserver to control at which size cache entries get cached in memory
- Changed: Merged cache memory layer with cache disk layer to reduce memory and cpu overhead
Diffstat (limited to 'src/zenserver/cache/structuredcachestore.cpp')
| -rw-r--r-- | src/zenserver/cache/structuredcachestore.cpp | 165 |
1 files changed, 69 insertions, 96 deletions
diff --git a/src/zenserver/cache/structuredcachestore.cpp b/src/zenserver/cache/structuredcachestore.cpp index 77316a5dc..89123a70f 100644 --- a/src/zenserver/cache/structuredcachestore.cpp +++ b/src/zenserver/cache/structuredcachestore.cpp @@ -58,19 +58,15 @@ IsKnownBadBucketName(std::string_view Bucket) return false; } -ZenCacheNamespace::ZenCacheNamespace(GcManager& Gc, - JobQueue& JobQueue, - const std::filesystem::path& RootDir, - bool EnableReferenceCaching, - const ZenCacheMemoryLayer::Configuration MemLayerConfig) +ZenCacheNamespace::ZenCacheNamespace(GcManager& Gc, JobQueue& JobQueue, const std::filesystem::path& RootDir, const Configuration& Config) : m_Gc(Gc) -, m_RootDir(RootDir) , m_JobQueue(JobQueue) -, m_MemLayer(m_JobQueue, MemLayerConfig) -, m_DiskLayer(RootDir, EnableReferenceCaching) +, m_RootDir(RootDir) +, m_Configuration(Config) +, m_DiskLayer(m_JobQueue, m_RootDir, m_Configuration.DiskLayerConfig) { - ZEN_INFO("initializing structured cache at '{}'", RootDir); - CreateDirectories(RootDir); + ZEN_INFO("initializing structured cache at '{}'", m_RootDir); + CreateDirectories(m_RootDir); m_DiskLayer.DiscoverBuckets(); @@ -91,27 +87,13 @@ ZenCacheNamespace::Get(std::string_view InBucket, const IoHash& HashKey, ZenCach metrics::RequestStats::Scope StatsScope(m_GetOps, 0); - bool Ok = m_MemLayer.Get(InBucket, HashKey, OutValue); - - if (Ok) - { - ZEN_ASSERT(OutValue.Value.Size()); - StatsScope.SetBytes(OutValue.Value.Size()); - m_HitCount++; - return true; - } - - Ok = m_DiskLayer.Get(InBucket, HashKey, OutValue); + bool Ok = m_DiskLayer.Get(InBucket, HashKey, OutValue); if (Ok) { ZEN_ASSERT(OutValue.Value.Size()); StatsScope.SetBytes(OutValue.Value.Size()); - if (OutValue.Value.Size() <= m_DiskLayerSizeThreshold) - { - m_MemLayer.Put(InBucket, HashKey, OutValue); - } m_HitCount++; return true; } @@ -132,11 +114,6 @@ ZenCacheNamespace::Put(std::string_view InBucket, const IoHash& HashKey, const Z ZEN_ASSERT(Value.Value.Size()); m_DiskLayer.Put(InBucket, HashKey, Value, References); - - if (Value.Value.Size() <= m_DiskLayerSizeThreshold) - { - m_MemLayer.Put(InBucket, HashKey, Value); - } m_WriteCount++; } @@ -145,15 +122,11 @@ ZenCacheNamespace::DropBucket(std::string_view Bucket) { ZEN_INFO("dropping bucket '{}'", Bucket); - // TODO: should ensure this is done atomically across all layers + const bool Dropped = m_DiskLayer.DropBucket(Bucket); - const bool MemDropped = m_MemLayer.DropBucket(Bucket); - const bool DiskDropped = m_DiskLayer.DropBucket(Bucket); - const bool AnyDropped = MemDropped || DiskDropped; + ZEN_INFO("bucket '{}' was {}", Bucket, Dropped ? "dropped" : "not found"); - ZEN_INFO("bucket '{}' was {}", Bucket, AnyDropped ? "dropped" : "not found"); - - return AnyDropped; + return Dropped; } void @@ -166,7 +139,6 @@ ZenCacheNamespace::EnumerateBucketContents(std::string_view bool ZenCacheNamespace::Drop() { - m_MemLayer.Drop(); return m_DiskLayer.Drop(); } @@ -189,7 +161,6 @@ ZenCacheNamespace::ScrubStorage(ScrubContext& Ctx) m_LastScrubTime = Ctx.ScrubTimestamp(); m_DiskLayer.ScrubStorage(Ctx); - m_MemLayer.ScrubStorage(Ctx); } void @@ -201,10 +172,6 @@ ZenCacheNamespace::GatherReferences(GcContext& GcCtx) const auto Guard = MakeGuard([&] { ZEN_DEBUG("cache gathered all references from '{}' in {}", m_RootDir, NiceTimeSpanMs(Timer.GetElapsedTimeMs())); }); - access_tracking::AccessTimes AccessTimes; - m_MemLayer.GatherAccessTimes(AccessTimes); - - m_DiskLayer.UpdateAccessTimes(AccessTimes); m_DiskLayer.GatherReferences(GcCtx); } @@ -213,31 +180,24 @@ ZenCacheNamespace::CollectGarbage(GcContext& GcCtx) { ZEN_TRACE_CPU("Z$::Namespace::CollectGarbage"); - (void)m_MemLayer.CollectGarbage(GcCtx.CacheExpireTime()); m_DiskLayer.CollectGarbage(GcCtx); } GcStorageSize ZenCacheNamespace::StorageSize() const { - return {.DiskSize = m_DiskLayer.TotalSize(), .MemorySize = m_MemLayer.TotalSize()}; + return m_DiskLayer.StorageSize(); } ZenCacheNamespace::Info ZenCacheNamespace::GetInfo() const { - ZenCacheNamespace::Info Info = {.Config = {.RootDir = m_RootDir, .DiskLayerThreshold = m_DiskLayerSizeThreshold}, - .DiskLayerInfo = m_DiskLayer.GetInfo(), - .MemoryLayerInfo = m_MemLayer.GetInfo()}; + ZenCacheNamespace::Info Info = {.RootDir = m_RootDir, .Config = m_Configuration, .DiskLayerInfo = m_DiskLayer.GetInfo()}; std::unordered_set<std::string> BucketNames; for (const std::string& BucketName : Info.DiskLayerInfo.BucketNames) { BucketNames.insert(BucketName); } - for (const std::string& BucketName : Info.MemoryLayerInfo.BucketNames) - { - BucketNames.insert(BucketName); - } Info.BucketNames.insert(Info.BucketNames.end(), BucketNames.begin(), BucketNames.end()); return Info; } @@ -250,8 +210,7 @@ ZenCacheNamespace::GetBucketInfo(std::string_view Bucket) const { return {}; } - ZenCacheNamespace::BucketInfo Info = {.DiskLayerInfo = *DiskBucketInfo, - .MemoryLayerInfo = m_MemLayer.GetBucketInfo(Bucket).value_or(ZenCacheMemoryLayer::BucketInfo{})}; + ZenCacheNamespace::BucketInfo Info = {.DiskLayerInfo = *DiskBucketInfo}; return Info; } @@ -278,23 +237,25 @@ ZEN_DEFINE_LOG_CATEGORY_STATIC(LogCacheActivity, "z$"); static constinit std::string_view UE4DDCNamespaceName = "ue4.ddc"; -ZenCacheStore::ZenCacheStore(GcManager& Gc, - JobQueue& JobQueue, - const Configuration& Configuration, - const DiskWriteBlocker* InDiskWriteBlocker) +ZenCacheStore::ZenCacheStore(GcManager& Gc, + JobQueue& JobQueue, + const std::filesystem::path& BasePath, + const Configuration& Configuration, + const DiskWriteBlocker* InDiskWriteBlocker) : m_DiskWriteBlocker(InDiskWriteBlocker) , m_Gc(Gc) , m_JobQueue(JobQueue) +, m_BasePath(BasePath) , m_Configuration(Configuration) , m_ExitLogging(false) { SetLoggingConfig(m_Configuration.Logging); - CreateDirectories(m_Configuration.BasePath); + CreateDirectories(m_BasePath); - ZEN_INFO("initializing cache store at '{}'", m_Configuration.BasePath); + ZEN_INFO("initializing cache store at '{}'", m_BasePath); DirectoryContent DirContent; - GetDirectoryContent(m_Configuration.BasePath, DirectoryContent::IncludeDirsFlag, DirContent); + GetDirectoryContent(m_BasePath, DirectoryContent::IncludeDirsFlag, DirContent); std::vector<std::string> Namespaces; for (const std::filesystem::path& DirPath : DirContent.Directories) @@ -307,14 +268,13 @@ ZenCacheStore::ZenCacheStore(GcManager& Gc, } } - ZEN_INFO("Found {} namespaces in '{}'", Namespaces.size(), m_Configuration.BasePath); + ZEN_INFO("Found {} namespaces in '{}'", Namespaces.size(), m_BasePath); if (std::find(Namespaces.begin(), Namespaces.end(), UE4DDCNamespaceName) == Namespaces.end()) { // default (unspecified) and ue4-ddc namespace points to the same namespace instance - std::filesystem::path DefaultNamespaceFolder = - m_Configuration.BasePath / fmt::format("{}{}", NamespaceDiskPrefix, UE4DDCNamespaceName); + std::filesystem::path DefaultNamespaceFolder = m_BasePath / fmt::format("{}{}", NamespaceDiskPrefix, UE4DDCNamespaceName); CreateDirectories(DefaultNamespaceFolder); Namespaces.push_back(std::string(UE4DDCNamespaceName)); } @@ -324,15 +284,14 @@ ZenCacheStore::ZenCacheStore(GcManager& Gc, m_Namespaces[NamespaceName] = std::make_unique<ZenCacheNamespace>(Gc, m_JobQueue, - m_Configuration.BasePath / fmt::format("{}{}", NamespaceDiskPrefix, NamespaceName), - m_Configuration.EnableReferenceCaching, - m_Configuration.MemLayerConfig); + m_BasePath / fmt::format("{}{}", NamespaceDiskPrefix, NamespaceName), + m_Configuration.NamespaceConfig); } } ZenCacheStore::~ZenCacheStore() { - ZEN_INFO("closing cache store at '{}'", m_Configuration.BasePath); + ZEN_INFO("closing cache store at '{}'", m_BasePath); SetLoggingConfig({.EnableWriteLog = false, .EnableAccessLog = false}); m_Namespaces.clear(); } @@ -564,7 +523,7 @@ ZenCacheStore::DropNamespace(std::string_view InNamespace) void ZenCacheStore::Flush() { - ZEN_INFO("flushing cache store at '{}'", m_Configuration.BasePath); + ZEN_INFO("flushing cache store at '{}'", m_BasePath); IterateNamespaces([&](std::string_view, ZenCacheNamespace& Store) { Store.Flush(); }); } @@ -632,13 +591,12 @@ ZenCacheStore::GetNamespace(std::string_view Namespace) return It->second.get(); } - auto NewNamespace = m_Namespaces.insert_or_assign( - std::string(Namespace), - std::make_unique<ZenCacheNamespace>(m_Gc, - m_JobQueue, - m_Configuration.BasePath / fmt::format("{}{}", NamespaceDiskPrefix, Namespace), - m_Configuration.EnableReferenceCaching, - m_Configuration.MemLayerConfig)); + auto NewNamespace = + m_Namespaces.insert_or_assign(std::string(Namespace), + std::make_unique<ZenCacheNamespace>(m_Gc, + m_JobQueue, + m_BasePath / fmt::format("{}{}", NamespaceDiskPrefix, Namespace), + m_Configuration.NamespaceConfig)); return NewNamespace.first->second.get(); } @@ -754,7 +712,6 @@ ZenCacheStore::GetInfo() const Info.NamespaceNames.push_back(std::string(NamespaceName)); ZenCacheNamespace::Info NamespaceInfo = Namespace.GetInfo(); Info.DiskEntryCount += NamespaceInfo.DiskLayerInfo.EntryCount; - Info.MemoryEntryCount += NamespaceInfo.MemoryLayerInfo.EntryCount; }); return Info; @@ -816,7 +773,7 @@ TEST_CASE("z$.store") GcManager Gc; auto JobQueue = MakeJobQueue(1, "testqueue"); - ZenCacheNamespace Zcs(Gc, *JobQueue, TempDir.Path() / "cache", false); + ZenCacheNamespace Zcs(Gc, *JobQueue, TempDir.Path() / "cache", {}); const int kIterationCount = 100; @@ -872,9 +829,9 @@ TEST_CASE("z$.size") { GcManager Gc; - ZenCacheNamespace Zcs(Gc, *JobQueue, TempDir.Path() / "cache", false); + ZenCacheNamespace Zcs(Gc, *JobQueue, TempDir.Path() / "cache", {}); - CbObject CacheValue = CreateCacheValue(Zcs.DiskLayerThreshold() - 256); + CbObject CacheValue = CreateCacheValue(Zcs.GetConfig().DiskLayerConfig.BucketConfig.MemCacheSizeThreshold - 256); IoBuffer Buffer = CacheValue.GetBuffer().AsIoBuffer(); Buffer.SetContentType(ZenContentType::kCbObject); @@ -895,7 +852,7 @@ TEST_CASE("z$.size") { GcManager Gc; - ZenCacheNamespace Zcs(Gc, *JobQueue, TempDir.Path() / "cache", false); + ZenCacheNamespace Zcs(Gc, *JobQueue, TempDir.Path() / "cache", {}); const GcStorageSize SerializedSize = Zcs.StorageSize(); CHECK_EQ(SerializedSize.MemorySize, 0); @@ -906,6 +863,7 @@ TEST_CASE("z$.size") Zcs.DropBucket(fmt::format("test_bucket-{}", Bucket)); } CHECK_EQ(0, Zcs.StorageSize().DiskSize); + CHECK_EQ(0, Zcs.StorageSize().MemorySize); } } @@ -918,9 +876,9 @@ TEST_CASE("z$.size") { GcManager Gc; - ZenCacheNamespace Zcs(Gc, *JobQueue, TempDir.Path() / "cache", false); + ZenCacheNamespace Zcs(Gc, *JobQueue, TempDir.Path() / "cache", {}); - CbObject CacheValue = CreateCacheValue(Zcs.DiskLayerThreshold() + 64); + CbObject CacheValue = CreateCacheValue(Zcs.GetConfig().DiskLayerConfig.BucketConfig.MemCacheSizeThreshold + 64); IoBuffer Buffer = CacheValue.GetBuffer().AsIoBuffer(); Buffer.SetContentType(ZenContentType::kCbObject); @@ -938,7 +896,7 @@ TEST_CASE("z$.size") { GcManager Gc; - ZenCacheNamespace Zcs(Gc, *JobQueue, TempDir.Path() / "cache", false); + ZenCacheNamespace Zcs(Gc, *JobQueue, TempDir.Path() / "cache", {}); const GcStorageSize SerializedSize = Zcs.StorageSize(); CHECK_EQ(SerializedSize.MemorySize, 0); @@ -977,7 +935,10 @@ TEST_CASE("z$.gc") { GcManager Gc; - ZenCacheNamespace Zcs(Gc, *JobQueue, TempDir.Path() / "cache", true); + ZenCacheNamespace Zcs(Gc, + *JobQueue, + TempDir.Path() / "cache", + {.DiskLayerConfig = {.BucketConfig = {.EnableReferenceCaching = true}}}); const auto Bucket = "teardrinker"sv; // Create a cache record @@ -1014,7 +975,10 @@ TEST_CASE("z$.gc") // Expect timestamps to be serialized { GcManager Gc; - ZenCacheNamespace Zcs(Gc, *JobQueue, TempDir.Path() / "cache", true); + ZenCacheNamespace Zcs(Gc, + *JobQueue, + TempDir.Path() / "cache", + {.DiskLayerConfig = {.BucketConfig = {.EnableReferenceCaching = true}}}); std::vector<IoHash> Keep; // Collect garbage with 1 hour max cache duration @@ -1035,7 +999,10 @@ TEST_CASE("z$.gc") { ScopedTemporaryDirectory TempDir; GcManager Gc; - ZenCacheNamespace Zcs(Gc, *JobQueue, TempDir.Path() / "cache", true); + ZenCacheNamespace Zcs(Gc, + *JobQueue, + TempDir.Path() / "cache", + {.DiskLayerConfig = {.BucketConfig = {.EnableReferenceCaching = true}}}); const auto Bucket = "fortysixandtwo"sv; const GcClock::TimePoint CurrentTime = GcClock::Now(); @@ -1081,7 +1048,10 @@ TEST_CASE("z$.gc") ScopedTemporaryDirectory TempDir; GcManager Gc; { - ZenCacheNamespace Zcs(Gc, *JobQueue, TempDir.Path() / "cache", true); + ZenCacheNamespace Zcs(Gc, + *JobQueue, + TempDir.Path() / "cache", + {.DiskLayerConfig = {.BucketConfig = {.EnableReferenceCaching = true}}}); const auto Bucket = "rightintwo"sv; std::vector<IoHash> Keys{CreateKey(1), CreateKey(2), CreateKey(3)}; @@ -1126,7 +1096,10 @@ TEST_CASE("z$.gc") } { // Unreferenced blocks will be pruned so size should now be zero - ZenCacheNamespace Zcs(Gc, *JobQueue, TempDir.Path() / "cache", true); + ZenCacheNamespace Zcs(Gc, + *JobQueue, + TempDir.Path() / "cache", + {.DiskLayerConfig = {.BucketConfig = {.EnableReferenceCaching = true}}}); CHECK_EQ(0, Zcs.StorageSize().DiskSize); } } @@ -1183,7 +1156,7 @@ TEST_CASE("z$.threadedinsert") // * doctest::skip(true)) WorkerThreadPool ThreadPool(4); GcManager Gc; auto JobQueue = MakeJobQueue(1, "testqueue"); - ZenCacheNamespace Zcs(Gc, *JobQueue, TempDir.Path(), true); + ZenCacheNamespace Zcs(Gc, *JobQueue, TempDir.Path(), {.DiskLayerConfig = {.BucketConfig = {.EnableReferenceCaching = true}}}); { std::atomic<size_t> WorkCompleted = 0; @@ -1402,7 +1375,7 @@ TEST_CASE("z$.namespaces") IoHash Key2; { GcManager Gc; - ZenCacheStore Zcs(Gc, *JobQueue, {.BasePath = TempDir.Path() / "cache", .AllowAutomaticCreationOfNamespaces = false}, nullptr); + ZenCacheStore Zcs(Gc, *JobQueue, TempDir.Path() / "cache", {.AllowAutomaticCreationOfNamespaces = false}, nullptr); const auto Bucket = "teardrinker"sv; const auto CustomNamespace = "mynamespace"sv; @@ -1427,7 +1400,7 @@ TEST_CASE("z$.namespaces") { GcManager Gc; - ZenCacheStore Zcs(Gc, *JobQueue, {.BasePath = TempDir.Path() / "cache", .AllowAutomaticCreationOfNamespaces = true}, nullptr); + ZenCacheStore Zcs(Gc, *JobQueue, TempDir.Path() / "cache", {.AllowAutomaticCreationOfNamespaces = true}, nullptr); const auto Bucket = "teardrinker"sv; const auto CustomNamespace = "mynamespace"sv; @@ -1490,7 +1463,7 @@ TEST_CASE("z$.drop.bucket") WorkerThreadPool Workers(1); { GcManager Gc; - ZenCacheStore Zcs(Gc, *JobQueue, {.BasePath = TempDir.Path() / "cache", .AllowAutomaticCreationOfNamespaces = true}, nullptr); + ZenCacheStore Zcs(Gc, *JobQueue, TempDir.Path() / "cache", {.AllowAutomaticCreationOfNamespaces = true}, nullptr); const auto Bucket = "teardrinker"sv; const auto Namespace = "mynamespace"sv; @@ -1563,7 +1536,7 @@ TEST_CASE("z$.drop.namespace") WorkerThreadPool Workers(1); { GcManager Gc; - ZenCacheStore Zcs(Gc, *JobQueue, {.BasePath = TempDir.Path() / "cache", .AllowAutomaticCreationOfNamespaces = true}, nullptr); + ZenCacheStore Zcs(Gc, *JobQueue, TempDir.Path() / "cache", {.AllowAutomaticCreationOfNamespaces = true}, nullptr); const auto Bucket1 = "teardrinker1"sv; const auto Bucket2 = "teardrinker2"sv; const auto Namespace1 = "mynamespace1"sv; @@ -1629,7 +1602,7 @@ TEST_CASE("z$.blocked.disklayer.put") GcManager Gc; auto JobQueue = MakeJobQueue(1, "testqueue"); - ZenCacheNamespace Zcs(Gc, *JobQueue, TempDir.Path() / "cache", false); + ZenCacheNamespace Zcs(Gc, *JobQueue, TempDir.Path() / "cache", {}); CbObject CacheValue = CreateCacheValue(64 * 1024 + 64); @@ -1724,7 +1697,7 @@ TEST_CASE("z$.scrub") GcManager Gc; CidStore CidStore(Gc); auto JobQueue = MakeJobQueue(1, "testqueue"); - ZenCacheNamespace Zcs(Gc, *JobQueue, TempDir.Path() / "cache", true); + ZenCacheNamespace Zcs(Gc, *JobQueue, TempDir.Path() / "cache", {}); CidStoreConfiguration CidConfig = {.RootDirectory = TempDir.Path() / "cas", .TinyValueThreshold = 1024, .HugeValueThreshold = 4096}; CidStore.Initialize(CidConfig); |