aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2024-09-17 15:05:40 +0200
committerGitHub Enterprise <[email protected]>2024-09-17 15:05:40 +0200
commitd020b6522b2d962db67f8a66410e74d61cf3da24 (patch)
tree44985edb66e5405df2d3a57c291490b2a0485337 /src
parentRunning the public github release mirroring as part of creating the release (... (diff)
downloadzen-d020b6522b2d962db67f8a66410e74d61cf3da24.tar.xz
zen-d020b6522b2d962db67f8a66410e74d61cf3da24.zip
gc performance improvements (#160)
* optimized ValidateCbUInt * optimized iohash comparision * replace unordered set/map with tsl/robin set/map in blockstore * increase max buffer size when writing cache bucket sidecar * only store meta data for files < 4Gb * faster ReadAttachmentsFromMetaData * remove memcpy call in BlockStoreDiskLocation * only write cache bucket state to disk if GC deleted anything
Diffstat (limited to 'src')
-rw-r--r--src/zencore/compactbinaryvalidation.cpp27
-rw-r--r--src/zencore/include/zencore/iohash.h15
-rw-r--r--src/zenstore/blockstore.cpp6
-rw-r--r--src/zenstore/cache/cachedisklayer.cpp129
-rw-r--r--src/zenstore/compactcas.cpp27
-rw-r--r--src/zenstore/include/zenstore/blockstore.h47
-rw-r--r--src/zenstore/include/zenstore/cache/cachedisklayer.h4
7 files changed, 145 insertions, 110 deletions
diff --git a/src/zencore/compactbinaryvalidation.cpp b/src/zencore/compactbinaryvalidation.cpp
index db830d250..82738e678 100644
--- a/src/zencore/compactbinaryvalidation.cpp
+++ b/src/zencore/compactbinaryvalidation.cpp
@@ -86,23 +86,24 @@ ValidateCbFieldType(MemoryView& View, CbValidateMode Mode, CbValidateError& Erro
static uint64_t
ValidateCbUInt(MemoryView& View, CbValidateMode Mode, CbValidateError& Error)
{
- if (View.GetSize() > 0 && View.GetSize() >= MeasureVarUInt(View.GetData()))
+ size_t ViewSize = View.GetSize();
+ if (ViewSize > 0)
{
- uint32_t ValueByteCount;
- const uint64_t Value = ReadVarUInt(View.GetData(), ValueByteCount);
- if (EnumHasAnyFlags(Mode, CbValidateMode::Format) && ValueByteCount > MeasureVarUInt(Value))
+ uint32_t ValueByteCount = MeasureVarUInt(View.GetData());
+ if (ViewSize >= ValueByteCount)
{
- AddError(Error, CbValidateError::InvalidInteger);
+ const uint64_t Value = ReadMeasuredVarUInt(View.GetData(), ValueByteCount);
+ if (EnumHasAnyFlags(Mode, CbValidateMode::Format) && ValueByteCount != MeasureVarUInt(Value))
+ {
+ AddError(Error, CbValidateError::InvalidInteger);
+ }
+ View += ValueByteCount;
+ return Value;
}
- View += ValueByteCount;
- return Value;
- }
- else
- {
- AddError(Error, CbValidateError::OutOfBounds);
- View.Reset();
- return 0;
}
+ AddError(Error, CbValidateError::OutOfBounds);
+ View.Reset();
+ return 0;
}
/**
diff --git a/src/zencore/include/zencore/iohash.h b/src/zencore/include/zencore/iohash.h
index c70e98e47..ff902399e 100644
--- a/src/zencore/include/zencore/iohash.h
+++ b/src/zencore/include/zencore/iohash.h
@@ -61,7 +61,20 @@ struct IoHash
static const IoHash Zero; // Initialized to all zeros
inline auto operator<=>(const IoHash& rhs) const = default;
- inline bool operator==(const IoHash& rhs) const { return memcmp(Hash, rhs.Hash, sizeof Hash) == 0; }
+ inline bool operator==(const IoHash& rhs) const
+ {
+ const uint32_t* LhsHash = reinterpret_cast<const uint32_t*>(Hash);
+ const uint32_t* RhsHash = reinterpret_cast<const uint32_t*>(rhs.Hash);
+ return LhsHash[0] == RhsHash[0] && LhsHash[1] == RhsHash[1] && LhsHash[2] == RhsHash[2] && LhsHash[3] == RhsHash[3] &&
+ LhsHash[4] == RhsHash[4];
+ }
+ inline bool operator!=(const IoHash& rhs) const
+ {
+ const uint32_t* LhsHash = reinterpret_cast<const uint32_t*>(Hash);
+ const uint32_t* RhsHash = reinterpret_cast<const uint32_t*>(rhs.Hash);
+ return LhsHash[0] != RhsHash[0] || LhsHash[1] != RhsHash[1] || LhsHash[2] != RhsHash[2] || LhsHash[3] != RhsHash[3] ||
+ LhsHash[4] != RhsHash[4];
+ }
inline bool operator<(const IoHash& rhs) const { return memcmp(Hash, rhs.Hash, sizeof Hash) < 0; }
struct Hasher
diff --git a/src/zenstore/blockstore.cpp b/src/zenstore/blockstore.cpp
index e20888ae4..00a38c3b6 100644
--- a/src/zenstore/blockstore.cpp
+++ b/src/zenstore/blockstore.cpp
@@ -273,7 +273,7 @@ BlockStore::Initialize(const std::filesystem::path& BlocksBasePath, uint64_t Max
ZEN_ASSERT(MaxBlockCount > 0);
ZEN_ASSERT(IsPow2(MaxBlockCount));
- std::unordered_map<uint32_t, uint64_t> FoundBlocks;
+ tsl::robin_map<uint32_t, uint64_t> FoundBlocks;
m_TotalSize = 0;
m_BlocksBasePath = BlocksBasePath;
@@ -1302,8 +1302,8 @@ BlockStore::IterateChunks(const std::span<const BlockStoreLocation>& ChunkLocati
ZEN_LOG_SCOPE("iterating chunks from '{}'", m_BlocksBasePath);
- std::unordered_map<uint32_t, size_t> BlockIndexToBlockChunks;
- std::vector<std::vector<size_t>> BlocksChunks;
+ tsl::robin_map<uint32_t, size_t> BlockIndexToBlockChunks;
+ std::vector<std::vector<size_t>> BlocksChunks;
for (size_t ChunkIndex = 0; ChunkIndex < ChunkLocations.size(); ++ChunkIndex)
{
diff --git a/src/zenstore/cache/cachedisklayer.cpp b/src/zenstore/cache/cachedisklayer.cpp
index f2ec5ddda..110acba9e 100644
--- a/src/zenstore/cache/cachedisklayer.cpp
+++ b/src/zenstore/cache/cachedisklayer.cpp
@@ -18,6 +18,7 @@
#include <zenutil/workerpools.h>
#include <future>
+#include <limits>
//////////////////////////////////////////////////////////////////////////
@@ -72,8 +73,8 @@ namespace {
struct BucketMetaHeader
{
static constexpr uint32_t ExpectedMagic = 0x61'74'65'6d; // 'meta';
- static constexpr uint32_t Version1 = 1;
- static constexpr uint32_t CurrentVersion = Version1;
+ static constexpr uint32_t Version2 = 2;
+ static constexpr uint32_t CurrentVersion = Version2;
uint32_t Magic = ExpectedMagic;
uint32_t Version = CurrentVersion;
@@ -299,17 +300,18 @@ private:
uint64_t m_ManifestEntryCount = 0;
+#pragma pack(push)
+#pragma pack(4)
struct ManifestData
{
- IoHash Key; // 20
+ uint32_t RawSize; // 4
AccessTime Timestamp; // 4
IoHash RawHash; // 20
- uint32_t Padding_0; // 4
- size_t RawSize; // 8
- uint64_t Padding_1; // 8
+ IoHash Key; // 20
};
+#pragma pack(pop)
- static_assert(sizeof(ManifestData) == 64);
+ static_assert(sizeof(ManifestData) == 48);
};
void
@@ -375,10 +377,12 @@ BucketManifestSerializer::ParseManifest(RwLock::ExclusiveLockScope& Buck
{
uint64_t RawSize = RawSizeIt.AsUInt64();
IoHash RawHash = RawHashIt.AsHash();
- if (RawSize != 0 || RawHash != IoHash::Zero)
+ if ((RawSize != 0 || RawHash != IoHash::Zero) && RawSize <= std::numeric_limits<std::uint32_t>::max())
{
BucketPayload& Payload = Payloads[KeyIndex];
- Bucket.SetMetaData(BucketLock, Payload, BucketMetaData{.RawSize = RawSize, .RawHash = RawHash});
+ Bucket.SetMetaData(BucketLock,
+ Payload,
+ BucketMetaData{.RawSize = static_cast<std::uint32_t>(RawSize), .RawHash = RawHash});
}
}
@@ -547,7 +551,7 @@ BucketManifestSerializer::ReadSidecarFile(RwLock::ExclusiveLockScope& B
return false;
}
- if (Header.Version != BucketMetaHeader::Version1)
+ if (Header.Version != BucketMetaHeader::Version2)
{
ZEN_WARN("Failed to read sidecar file '{}'. Unsupported version: {}", SidecarPath, Header.Version);
return false;
@@ -635,7 +639,7 @@ BucketManifestSerializer::WriteSidecarFile(RwLock::SharedLockScope&,
// BasicFileWriter SidecarWriter(SidecarFile, 128 * 1024);
std::vector<ManifestData> ManifestDataBuffer;
- const size_t MaxManifestDataBufferCount = Min(Index.size(), 4096u); // 256 Kb
+ const size_t MaxManifestDataBufferCount = Min(Index.size(), 8192u); // 512 Kb
ManifestDataBuffer.reserve(MaxManifestDataBufferCount);
for (auto& Kv : Index)
{
@@ -643,7 +647,7 @@ BucketManifestSerializer::WriteSidecarFile(RwLock::SharedLockScope&,
const PayloadIndex PlIndex = Kv.second;
IoHash RawHash = IoHash::Zero;
- uint64_t RawSize = 0;
+ uint32_t RawSize = 0;
if (const MetaDataIndex MetaIndex = Payloads[PlIndex].MetaData)
{
@@ -651,12 +655,8 @@ BucketManifestSerializer::WriteSidecarFile(RwLock::SharedLockScope&,
RawSize = MetaDatas[MetaIndex].RawSize;
}
- ManifestDataBuffer.emplace_back(ManifestData{.Key = Key,
- .Timestamp = AccessTimes[PlIndex],
- .RawHash = RawHash,
- .Padding_0 = 0,
- .RawSize = RawSize,
- .Padding_1 = 0});
+ ManifestDataBuffer.emplace_back(
+ ManifestData{.RawSize = RawSize, .Timestamp = AccessTimes[PlIndex], .RawHash = RawHash, .Key = Key});
if (ManifestDataBuffer.size() == MaxManifestDataBufferCount)
{
const uint64_t WriteSize = sizeof(ManifestData) * ManifestDataBuffer.size();
@@ -1464,6 +1464,10 @@ ZenCacheDiskLayer::CacheBucket::EndGetBatch(GetBatchHandle* Batch) noexcept
OutValue.RawHash = IoHash::HashBuffer(OutValue.Value);
OutValue.RawSize = OutValue.Value.GetSize();
}
+ if (OutValue.RawSize > std::numeric_limits<std::uint32_t>::max())
+ {
+ SetMetaInfo = false;
+ }
}
if (SetMetaInfo || AddToMemCache)
@@ -1478,7 +1482,9 @@ ZenCacheDiskLayer::CacheBucket::EndGetBatch(GetBatchHandle* Batch) noexcept
// Only update if it has not already been updated by other thread
if (!Payload.MetaData && SetMetaInfo)
{
- SetMetaData(UpdateIndexLock, Payload, {.RawSize = OutValue.RawSize, .RawHash = OutValue.RawHash});
+ SetMetaData(UpdateIndexLock,
+ Payload,
+ {.RawSize = gsl::narrow<uint32_t>(OutValue.RawSize), .RawHash = OutValue.RawHash});
}
if (!Payload.MemCached && AddToMemCache)
{
@@ -1576,6 +1582,7 @@ ZenCacheDiskLayer::CacheBucket::EndGetBatch(GetBatchHandle* Batch) noexcept
OutValue.RawSize = OutValue.Value.GetSize();
}
+ if (OutValue.RawSize <= std::numeric_limits<std::uint32_t>::max())
{
RwLock::ExclusiveLockScope UpdateIndexLock(m_IndexLock);
{
@@ -1586,7 +1593,9 @@ ZenCacheDiskLayer::CacheBucket::EndGetBatch(GetBatchHandle* Batch) noexcept
// Only update if it has not already been updated by other thread
if (!Payload.MetaData)
{
- SetMetaData(UpdateIndexLock, Payload, {.RawSize = OutValue.RawSize, .RawHash = OutValue.RawHash});
+ SetMetaData(UpdateIndexLock,
+ Payload,
+ {.RawSize = static_cast<std::uint32_t>(OutValue.RawSize), .RawHash = OutValue.RawHash});
}
}
}
@@ -1724,15 +1733,20 @@ ZenCacheDiskLayer::CacheBucket::Get(const IoHash& HashKey, ZenCacheValue& OutVal
OutValue.RawHash = IoHash::HashBuffer(OutValue.Value);
OutValue.RawSize = OutValue.Value.GetSize();
}
- RwLock::ExclusiveLockScope UpdateIndexLock(m_IndexLock);
- if (auto WriteIt = m_Index.find(HashKey); WriteIt != m_Index.end())
+ if (OutValue.RawSize <= std::numeric_limits<std::uint32_t>::max())
{
- BucketPayload& WritePayload = m_Payloads[WriteIt.value()];
-
- // Only set if no other path has already updated the meta data
- if (!WritePayload.MetaData)
+ RwLock::ExclusiveLockScope UpdateIndexLock(m_IndexLock);
+ if (auto WriteIt = m_Index.find(HashKey); WriteIt != m_Index.end())
{
- SetMetaData(UpdateIndexLock, WritePayload, {.RawSize = OutValue.RawSize, .RawHash = OutValue.RawHash});
+ BucketPayload& WritePayload = m_Payloads[WriteIt.value()];
+
+ // Only set if no other path has already updated the meta data
+ if (!WritePayload.MetaData)
+ {
+ SetMetaData(UpdateIndexLock,
+ WritePayload,
+ {.RawSize = static_cast<std::uint32_t>(OutValue.RawSize), .RawHash = OutValue.RawHash});
+ }
}
}
}
@@ -2972,9 +2986,9 @@ ZenCacheDiskLayer::CacheBucket::PutStandaloneCacheValue(const IoHash& HashKey, c
RemoveMemCachedData(IndexLock, Payload);
m_StandaloneSize.fetch_sub(OldSize, std::memory_order::relaxed);
}
- if (Value.RawSize != 0 || Value.RawHash != IoHash::Zero)
+ if ((Value.RawSize != 0 || Value.RawHash != IoHash::Zero) && Value.RawSize <= std::numeric_limits<std::uint32_t>::max())
{
- SetMetaData(IndexLock, m_Payloads[EntryIndex], {.RawSize = Value.RawSize, .RawHash = Value.RawHash});
+ SetMetaData(IndexLock, m_Payloads[EntryIndex], {.RawSize = static_cast<std::uint32_t>(Value.RawSize), .RawHash = Value.RawHash});
}
else
{
@@ -3280,8 +3294,9 @@ public:
uint64_t ChunkSize = RoundUp(Loc.Size(), m_Bucket.m_Configuration.PayloadAlignment);
if (auto It = BlockUsage.find(BlockIndex); It != BlockUsage.end())
{
- It->second.EntryCount++;
- It->second.DiskUsage += ChunkSize;
+ BlockStore::BlockUsageInfo& Info = It.value();
+ Info.EntryCount++;
+ Info.DiskUsage += ChunkSize;
}
else
{
@@ -3411,20 +3426,23 @@ ZenCacheDiskLayer::CacheBucket::RemoveExpiredData(GcCtx& Ctx, GcStats& Stats)
NiceBytes(Stats.FreedMemory),
NiceTimeSpanMs(Timer.GetElapsedTimeMs()));
}
- bool Expected = false;
- if (m_IsFlushing || !m_IsFlushing.compare_exchange_strong(Expected, true))
+ if (Stats.DeletedCount > 0)
{
- return;
- }
- auto FlushingGuard = MakeGuard([&] { m_IsFlushing.store(false); });
+ bool Expected = false;
+ if (m_IsFlushing || !m_IsFlushing.compare_exchange_strong(Expected, true))
+ {
+ return;
+ }
+ auto FlushingGuard = MakeGuard([&] { m_IsFlushing.store(false); });
- try
- {
- SaveSnapshot([]() { return 0; });
- }
- catch (const std::exception& Ex)
- {
- ZEN_WARN("Failed to write index and manifest after RemoveExpiredData in '{}'. Reason: '{}'", m_BucketDir, Ex.what());
+ try
+ {
+ SaveSnapshot([]() { return 0; });
+ }
+ catch (const std::exception& Ex)
+ {
+ ZEN_WARN("Failed to write index and manifest after RemoveExpiredData in '{}'. Reason: '{}'", m_BucketDir, Ex.what());
+ }
}
});
@@ -3529,7 +3547,7 @@ ZenCacheDiskLayer::CacheBucket::ReadAttachmentsFromMetaData(uint32_t BlockI
IoBuffer MetaDataPayload = m_BlockStore.GetMetaData(BlockIndex);
if (MetaDataPayload)
{
- std::unordered_set<IoHash, IoHash::Hasher> WantedKeys;
+ tsl::robin_set<IoHash, IoHash::Hasher> WantedKeys;
WantedKeys.reserve(ChunkIndexes.size());
for (const size_t ChunkIndex : ChunkIndexes)
{
@@ -3540,20 +3558,29 @@ ZenCacheDiskLayer::CacheBucket::ReadAttachmentsFromMetaData(uint32_t BlockI
MetaDataPayload,
BlockMetaDataExpectedMagic,
[&](std::span<const IoHash> Keys, std::span<const uint32_t> AttachmentCounts, std::span<const IoHash> Attachments) {
- OutReferences.reserve(OutReferences.capacity() + Attachments.size());
- auto AttachmentStart = Attachments.begin();
- for (uint32_t Index = 0; Index < Keys.size(); Index++)
+ auto AttachmentReadIt = Attachments.begin();
+ OutReferences.resize(OutReferences.size() + Attachments.size());
+ auto OutReferencesWriteIt = OutReferences.end() - Attachments.size();
+ auto KeyIt = Keys.begin();
+ for (uint32_t AttachmentCount : AttachmentCounts)
{
- uint32_t AttachmentCount = AttachmentCounts[Index];
if (AttachmentCount > 0)
{
- if (WantedKeys.contains(Keys[Index]))
+ if (WantedKeys.contains(*KeyIt))
+ {
+ for (uint32_t It = 0u; It < AttachmentCount; It++)
+ {
+ *OutReferencesWriteIt++ = *AttachmentReadIt++;
+ }
+ }
+ else
{
- OutReferences.insert(OutReferences.end(), AttachmentStart, AttachmentStart + AttachmentCount);
+ AttachmentReadIt += AttachmentCount;
}
- AttachmentStart += AttachmentCount;
}
+ KeyIt++;
}
+ OutReferences.erase(OutReferencesWriteIt, OutReferences.end());
});
}
return false;
diff --git a/src/zenstore/compactcas.cpp b/src/zenstore/compactcas.cpp
index 1e647b284..15f80d4cf 100644
--- a/src/zenstore/compactcas.cpp
+++ b/src/zenstore/compactcas.cpp
@@ -28,7 +28,7 @@
# include <algorithm>
# include <random>
ZEN_THIRD_PARTY_INCLUDES_START
-# include <tsl/robin_map.h>
+# include <tsl/robin_set.h>
ZEN_THIRD_PARTY_INCLUDES_END
#endif
@@ -728,10 +728,11 @@ public:
uint32_t BlockIndex = Loc.GetBlockIndex();
uint64_t ChunkSize = RoundUp(Loc.GetSize(), m_CasContainerStrategy.m_PayloadAlignment);
- if (auto It = BlockUsage.find(BlockIndex); It != BlockUsage.end())
+ if (BlockStore::BlockUsageMap::iterator It = BlockUsage.find(BlockIndex); It != BlockUsage.end())
{
- It->second.EntryCount++;
- It->second.DiskUsage += ChunkSize;
+ BlockStore::BlockUsageInfo& Info = It.value();
+ Info.EntryCount++;
+ Info.DiskUsage += ChunkSize;
}
else
{
@@ -1869,7 +1870,7 @@ TEST_CASE_TEMPLATE("compactcas.threadedinsert", GCV2, FalseType, TrueType)
const int32_t kChunkCount = 4096;
uint64_t ExpectedSize = 0;
- std::unordered_map<IoHash, IoBuffer, IoHash::Hasher> Chunks;
+ tsl::robin_map<IoHash, IoBuffer, IoHash::Hasher> Chunks;
Chunks.reserve(kChunkCount);
for (int32_t Idx = 0; Idx < kChunkCount; ++Idx)
@@ -1932,7 +1933,7 @@ TEST_CASE_TEMPLATE("compactcas.threadedinsert", GCV2, FalseType, TrueType)
}
}
- std::unordered_set<IoHash, IoHash::Hasher> GcChunkHashes;
+ tsl::robin_set<IoHash, IoHash::Hasher> GcChunkHashes;
GcChunkHashes.reserve(Chunks.size());
for (const auto& Chunk : Chunks)
{
@@ -1940,7 +1941,7 @@ TEST_CASE_TEMPLATE("compactcas.threadedinsert", GCV2, FalseType, TrueType)
}
{
WorkCompleted = 0;
- std::unordered_map<IoHash, IoBuffer, IoHash::Hasher> NewChunks;
+ tsl::robin_map<IoHash, IoBuffer, IoHash::Hasher> NewChunks;
NewChunks.reserve(kChunkCount);
for (int32_t Idx = 0; Idx < kChunkCount; ++Idx)
@@ -1974,8 +1975,8 @@ TEST_CASE_TEMPLATE("compactcas.threadedinsert", GCV2, FalseType, TrueType)
});
}
- std::unordered_set<IoHash, IoHash::Hasher> ChunksToDelete;
- std::vector<IoHash> KeepHashes(GcChunkHashes.begin(), GcChunkHashes.end());
+ tsl::robin_set<IoHash, IoHash::Hasher> ChunksToDelete;
+ std::vector<IoHash> KeepHashes(GcChunkHashes.begin(), GcChunkHashes.end());
size_t C = 0;
while (C < KeepHashes.size())
@@ -1998,10 +1999,10 @@ TEST_CASE_TEMPLATE("compactcas.threadedinsert", GCV2, FalseType, TrueType)
C++;
}
- auto DoGC = [](CasContainerStrategy& Cas,
- const std::unordered_set<IoHash, IoHash::Hasher>& ChunksToDelete,
- const std::vector<IoHash>& KeepHashes,
- std::unordered_set<IoHash, IoHash::Hasher>& GcChunkHashes) {
+ auto DoGC = [](CasContainerStrategy& Cas,
+ const tsl::robin_set<IoHash, IoHash::Hasher>& ChunksToDelete,
+ const std::vector<IoHash>& KeepHashes,
+ tsl::robin_set<IoHash, IoHash::Hasher>& GcChunkHashes) {
if (GCV2::Enabled)
{
std::atomic_bool IsCancelledFlag = false;
diff --git a/src/zenstore/include/zenstore/blockstore.h b/src/zenstore/include/zenstore/blockstore.h
index 8f67c1c0f..29c53cf22 100644
--- a/src/zenstore/include/zenstore/blockstore.h
+++ b/src/zenstore/include/zenstore/blockstore.h
@@ -6,7 +6,10 @@
#include <zencore/zencore.h>
#include <zenutil/basicfile.h>
-#include <unordered_map>
+ZEN_THIRD_PARTY_INCLUDES_START
+#include <tsl/robin_map.h>
+ZEN_THIRD_PARTY_INCLUDES_END
+
#include <unordered_set>
namespace zen {
@@ -29,8 +32,8 @@ struct BlockStoreDiskLocation
{
constexpr static uint32_t MaxBlockIndexBits = 20;
constexpr static uint32_t MaxOffsetBits = 28;
- constexpr static uint32_t MaxBlockIndex = (1ul << BlockStoreDiskLocation::MaxBlockIndexBits) - 1ul;
- constexpr static uint32_t MaxOffset = (1ul << BlockStoreDiskLocation::MaxOffsetBits) - 1ul;
+ constexpr static uint32_t MaxBlockIndex = (1ul << MaxBlockIndexBits) - 1ul;
+ constexpr static uint32_t MaxOffset = (1ul << MaxOffsetBits) - 1ul;
BlockStoreDiskLocation(const BlockStoreLocation& Location, uint32_t OffsetAlignment)
{
@@ -41,26 +44,15 @@ struct BlockStoreDiskLocation
inline BlockStoreLocation Get(uint32_t OffsetAlignment) const
{
- uint64_t PackedOffset = 0;
- memcpy(&PackedOffset, &m_Offset, sizeof m_Offset);
- return {.BlockIndex = static_cast<uint32_t>(PackedOffset >> MaxOffsetBits),
- .Offset = static_cast<uint32_t>((PackedOffset & MaxOffset) * OffsetAlignment),
- .Size = GetSize()};
+ return {.BlockIndex = GetBlockIndex(), .Offset = GetOffset(OffsetAlignment), .Size = GetSize()};
}
inline uint32_t GetBlockIndex() const
{
- uint64_t PackedOffset = 0;
- memcpy(&PackedOffset, &m_Offset, sizeof m_Offset);
- return static_cast<std::uint32_t>(PackedOffset >> MaxOffsetBits);
+ return (m_OffsetAndSize1 >> MaxOffsetBits) + (static_cast<uint32_t>(m_OffsetAndSize2) << (32u - MaxOffsetBits));
}
- inline uint32_t GetOffset(uint32_t OffsetAlignment) const
- {
- uint64_t PackedOffset = 0;
- memcpy(&PackedOffset, &m_Offset, sizeof m_Offset);
- return static_cast<uint32_t>((PackedOffset & MaxOffset) * OffsetAlignment);
- }
+ inline uint32_t GetOffset(uint32_t OffsetAlignment) const { return ((m_OffsetAndSize1)&0x0fffffffu) * OffsetAlignment; }
inline uint32_t GetSize() const { return m_Size; }
@@ -73,13 +65,14 @@ private:
ZEN_ASSERT(Offset <= MaxOffset);
ZEN_ASSERT(Size <= std::numeric_limits<std::uint32_t>::max());
- m_Size = static_cast<uint32_t>(Size);
- uint64_t PackedOffset = (static_cast<uint64_t>(BlockIndex) << MaxOffsetBits) + Offset;
- memcpy(&m_Offset[0], &PackedOffset, sizeof m_Offset);
+ m_Size = static_cast<uint32_t>(Size);
+ m_OffsetAndSize1 = (Offset & 0x0fffffffu) + (BlockIndex << MaxOffsetBits);
+ m_OffsetAndSize2 = static_cast<uint16_t>((BlockIndex >> (32u - MaxOffsetBits)) & 0xffffu);
}
uint32_t m_Size;
- uint8_t m_Offset[6];
+ uint32_t m_OffsetAndSize1;
+ uint16_t m_OffsetAndSize2;
};
static_assert(sizeof(BlockStoreDiskLocation) == 10);
@@ -146,8 +139,8 @@ public:
uint64_t DiskUsage;
uint32_t EntryCount;
};
- typedef std::unordered_map<uint32_t, BlockUsageInfo> BlockUsageMap;
- typedef std::unordered_map<uint32_t, uint32_t> BlockEntryCountMap;
+ typedef tsl::robin_map<uint32_t, BlockUsageInfo> BlockUsageMap;
+ typedef tsl::robin_map<uint32_t, uint32_t> BlockEntryCountMap;
void Initialize(const std::filesystem::path& BlocksBasePath, uint64_t MaxBlockSize, uint64_t MaxBlockCount);
@@ -212,7 +205,7 @@ private:
static std::filesystem::path GetBlockPath(const std::filesystem::path& BlocksBasePath, const uint32_t BlockIndex);
uint32_t GetFreeBlockIndex(uint32_t StartProbeIndex, RwLock::ExclusiveLockScope&, std::filesystem::path& OutBlockPath) const;
- std::unordered_map<uint32_t, Ref<BlockStoreFile>> m_ChunkBlocks;
+ tsl::robin_map<uint32_t, Ref<BlockStoreFile>> m_ChunkBlocks;
mutable RwLock m_InsertLock; // used to serialize inserts
Ref<BlockStoreFile> m_WriteBlock;
@@ -290,9 +283,9 @@ public:
}
private:
- std::unordered_map<uint32_t, size_t> m_BlockIndexToChunkMapIndex; // Maps to which vector in BlockKeepChunks to use for a block
- std::vector<std::vector<size_t>> m_KeepChunks; // One vector per block index with index into ChunkLocations
- std::vector<BlockStoreLocation> m_ChunkLocations;
+ tsl::robin_map<uint32_t, size_t> m_BlockIndexToChunkMapIndex; // Maps to which vector in BlockKeepChunks to use for a block
+ std::vector<std::vector<size_t>> m_KeepChunks; // One vector per block index with index into ChunkLocations
+ std::vector<BlockStoreLocation> m_ChunkLocations;
};
void blockstore_forcelink();
diff --git a/src/zenstore/include/zenstore/cache/cachedisklayer.h b/src/zenstore/include/zenstore/cache/cachedisklayer.h
index 0afc80953..b0b8b4cf3 100644
--- a/src/zenstore/include/zenstore/cache/cachedisklayer.h
+++ b/src/zenstore/include/zenstore/cache/cachedisklayer.h
@@ -302,7 +302,7 @@ public:
};
struct BucketMetaData
{
- uint64_t RawSize = 0; // 8
+ uint32_t RawSize = 0; // 4
IoHash RawHash; // 20
operator bool() const { return RawSize != 0 || RawHash != IoHash::Zero; };
@@ -314,7 +314,7 @@ public:
};
#pragma pack(pop)
static_assert(sizeof(BucketPayload) == 20u);
- static_assert(sizeof(BucketMetaData) == 28u);
+ static_assert(sizeof(BucketMetaData) == 24u);
static_assert(sizeof(AccessTime) == 4u);
using IndexMap = tsl::robin_map<IoHash, PayloadIndex, IoHash::Hasher>;