diff options
| author | Dan Engelbrecht <[email protected]> | 2024-09-17 15:05:40 +0200 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2024-09-17 15:05:40 +0200 |
| commit | d020b6522b2d962db67f8a66410e74d61cf3da24 (patch) | |
| tree | 44985edb66e5405df2d3a57c291490b2a0485337 /src | |
| parent | Running the public github release mirroring as part of creating the release (... (diff) | |
| download | zen-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.cpp | 27 | ||||
| -rw-r--r-- | src/zencore/include/zencore/iohash.h | 15 | ||||
| -rw-r--r-- | src/zenstore/blockstore.cpp | 6 | ||||
| -rw-r--r-- | src/zenstore/cache/cachedisklayer.cpp | 129 | ||||
| -rw-r--r-- | src/zenstore/compactcas.cpp | 27 | ||||
| -rw-r--r-- | src/zenstore/include/zenstore/blockstore.h | 47 | ||||
| -rw-r--r-- | src/zenstore/include/zenstore/cache/cachedisklayer.h | 4 |
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>; |