aboutsummaryrefslogtreecommitdiff
path: root/src/zenserver/cache/structuredcachestore.cpp
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2023-10-24 14:54:26 +0200
committerGitHub <[email protected]>2023-10-24 14:54:26 +0200
commit1a144212278aa7158d6b32b63e398db95a7ae868 (patch)
tree58735827b0b706368a82bcaaa8aaa68f211e1d10 /src/zenserver/cache/structuredcachestore.cpp
parentchunking moved to zenstore (#490) (diff)
downloadzen-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.cpp165
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);