aboutsummaryrefslogtreecommitdiff
path: root/zenserver/cache/structuredcachestore.h
diff options
context:
space:
mode:
Diffstat (limited to 'zenserver/cache/structuredcachestore.h')
-rw-r--r--zenserver/cache/structuredcachestore.h107
1 files changed, 65 insertions, 42 deletions
diff --git a/zenserver/cache/structuredcachestore.h b/zenserver/cache/structuredcachestore.h
index e6e9942bb..3d2896ff8 100644
--- a/zenserver/cache/structuredcachestore.h
+++ b/zenserver/cache/structuredcachestore.h
@@ -132,13 +132,48 @@ struct DiskIndexEntry
static_assert(sizeof(DiskIndexEntry) == 32);
+// This store the access time as seconds since epoch internally in a 32-bit value giving is a range of 136 years since epoch
+struct AccessTime
+{
+ explicit AccessTime(GcClock::Tick Tick) noexcept : SecondsSinceEpoch(ToSeconds(Tick)) {}
+ AccessTime& operator=(GcClock::Tick Tick) noexcept
+ {
+ SecondsSinceEpoch.store(ToSeconds(Tick), std::memory_order_relaxed);
+ return *this;
+ }
+ operator GcClock::Tick() const noexcept
+ {
+ return std::chrono::duration_cast<GcClock::Duration>(std::chrono::seconds(SecondsSinceEpoch.load(std::memory_order_relaxed)))
+ .count();
+ }
+
+ AccessTime(AccessTime&& Rhs) noexcept : SecondsSinceEpoch(Rhs.SecondsSinceEpoch.load(std::memory_order_relaxed)) {}
+ AccessTime(const AccessTime& Rhs) noexcept : SecondsSinceEpoch(Rhs.SecondsSinceEpoch.load(std::memory_order_relaxed)) {}
+ AccessTime& operator=(AccessTime&& Rhs) noexcept
+ {
+ SecondsSinceEpoch.store(Rhs.SecondsSinceEpoch.load(std::memory_order_relaxed), std::memory_order_relaxed);
+ return *this;
+ }
+ AccessTime& operator=(const AccessTime& Rhs) noexcept
+ {
+ SecondsSinceEpoch.store(Rhs.SecondsSinceEpoch.load(std::memory_order_relaxed), std::memory_order_relaxed);
+ return *this;
+ }
+
+private:
+ static uint32_t ToSeconds(GcClock::Tick Tick)
+ {
+ return gsl::narrow<uint32_t>(std::chrono::duration_cast<std::chrono::seconds>(GcClock::Duration(Tick)).count());
+ }
+ std::atomic_uint32_t SecondsSinceEpoch;
+};
+
/** In-memory cache storage
Intended for small values which are frequently accessed
This should have a better memory management policy to maintain reasonable
footprint.
-
*/
class ZenCacheMemoryLayer
{
@@ -184,28 +219,24 @@ public:
private:
struct CacheBucket
{
- struct BucketValue
+#pragma pack(push)
+#pragma pack(1)
+ struct BucketPayload
{
- IoBuffer Payload;
- std::atomic_int64_t LastAccess;
-
- BucketValue() : Payload(), LastAccess() {}
- BucketValue(IoBuffer Value, const int64_t Timestamp) : Payload(Value), LastAccess(Timestamp) {}
- BucketValue(const BucketValue& V) : Payload(V.Payload), LastAccess(V.LastAccess.load(std::memory_order_relaxed)) {}
- BucketValue(BucketValue&& V) : Payload(std::move(V.Payload)), LastAccess(V.LastAccess.load(std::memory_order_relaxed)) {}
-
- BucketValue& operator=(const BucketValue& V) { return *this = BucketValue(V); }
- BucketValue& operator=(BucketValue&& V)
- {
- Payload = std::move(V.Payload);
- LastAccess.store(V.LastAccess.load(), std::memory_order_relaxed);
- return *this;
- }
+ IoBuffer Payload; // 8
+ uint32_t RawSize; // 4
+ IoHash RawHash; // 20
};
+#pragma pack(pop)
+ static_assert(sizeof(BucketPayload) == 32u);
+ static_assert(sizeof(AccessTime) == 4u);
+
+ mutable RwLock m_BucketLock;
+ std::vector<AccessTime> m_AccessTimes;
+ std::vector<BucketPayload> m_Payloads;
+ tsl::robin_map<IoHash, uint32_t> m_CacheMap;
- mutable RwLock m_BucketLock;
- tsl::robin_map<IoHash, BucketValue> m_CacheMap;
- std::atomic_uint64_t m_TotalSize{};
+ std::atomic_uint64_t m_TotalSize{};
bool Get(const IoHash& HashKey, ZenCacheValue& OutValue);
void Put(const IoHash& HashKey, const ZenCacheValue& Value);
@@ -259,7 +290,6 @@ public:
void GatherReferences(GcContext& GcCtx);
void CollectGarbage(GcContext& GcCtx);
void UpdateAccessTimes(const zen::access_tracking::AccessTimes& AccessTimes);
- // void IterateBuckets(const std::function<void(std::string_view Bucket)>& Callback) const;
void DiscoverBuckets();
uint64_t TotalSize() const;
@@ -305,31 +335,24 @@ private:
TCasLogFile<DiskIndexEntry> m_SlogFile;
uint64_t m_LogFlushPosition = 0;
- struct IndexEntry
+#pragma pack(push)
+#pragma pack(1)
+ struct BucketPayload
{
- DiskLocation Location;
- std::atomic_int64_t LastAccess;
-
- IndexEntry() : Location(), LastAccess() {}
- IndexEntry(const DiskLocation& Loc, const int64_t Timestamp) : Location(Loc), LastAccess(Timestamp) {}
- IndexEntry(const IndexEntry& E) : Location(E.Location), LastAccess(E.LastAccess.load(std::memory_order_relaxed)) {}
- IndexEntry(IndexEntry&& E) noexcept : Location(std::move(E.Location)), LastAccess(E.LastAccess.load(std::memory_order_relaxed))
- {
- }
-
- IndexEntry& operator=(const IndexEntry& E) { return *this = IndexEntry(E); }
- IndexEntry& operator=(IndexEntry&& E) noexcept
- {
- Location = std::move(E.Location);
- LastAccess.store(E.LastAccess.load(), std::memory_order_relaxed);
- return *this;
- }
+ DiskLocation Location; // 12
+ uint64_t RawSize; // 8
+ IoHash RawHash; // 20
};
+#pragma pack(pop)
+ static_assert(sizeof(BucketPayload) == 40u);
+ static_assert(sizeof(AccessTime) == 4u);
- using IndexMap = tsl::robin_map<IoHash, IndexEntry, IoHash::Hasher>;
+ using IndexMap = tsl::robin_map<IoHash, size_t, IoHash::Hasher>;
- mutable RwLock m_IndexLock;
- IndexMap m_Index;
+ mutable RwLock m_IndexLock;
+ std::vector<AccessTime> m_AccessTimes;
+ std::vector<BucketPayload> m_Payloads;
+ IndexMap m_Index;
std::atomic_uint64_t m_TotalStandaloneSize{};