aboutsummaryrefslogtreecommitdiff
path: root/src/zenstore/blockstore.cpp
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2023-10-03 13:31:02 +0200
committerGitHub <[email protected]>2023-10-03 13:31:02 +0200
commit68a72b68592c416969bd36f413eb2b2762b9fcff (patch)
tree9a5fc28eb9040f010c92f86a1745f9418dfc91ca /src/zenstore/blockstore.cpp
parentclean up date formatting (#440) (diff)
downloadzen-68a72b68592c416969bd36f413eb2b2762b9fcff.tar.xz
zen-68a72b68592c416969bd36f413eb2b2762b9fcff.zip
faster accesstime save restore (#439)
- Improvement: Reduce time a cache bucket is locked for write when flushing/garbage collecting - Change format for faster read/write and reduced size on disk - Don't lock index while writing manifest to disk - Skip garbage collect if we are currently in a Flush operation - BlockStore::Flush no longer terminates currently writing block - Garbage collect references to currently writing block but keep the block as new data may be added - Fix BlockStore::Prune used disk space calculation - Don't materialize data in filecas when we just need the size
Diffstat (limited to 'src/zenstore/blockstore.cpp')
-rw-r--r--src/zenstore/blockstore.cpp84
1 files changed, 45 insertions, 39 deletions
diff --git a/src/zenstore/blockstore.cpp b/src/zenstore/blockstore.cpp
index b5ed17fc6..f99b0bc4a 100644
--- a/src/zenstore/blockstore.cpp
+++ b/src/zenstore/blockstore.cpp
@@ -233,7 +233,6 @@ BlockStore::Prune(const std::vector<BlockStoreLocation>& KnownLocations)
if (!KnownBlocks.contains(BlockIndex))
{
Ref<BlockStoreFile> BlockFile = m_ChunkBlocks[BlockIndex];
- m_TotalSize.fetch_add(BlockFile->FileSize(), std::memory_order::relaxed);
BlocksToDelete.push_back(BlockIndex);
}
}
@@ -242,6 +241,7 @@ BlockStore::Prune(const std::vector<BlockStoreLocation>& KnownLocations)
{
// Clear out unused blocks
Ref<BlockStoreFile> BlockFile = m_ChunkBlocks[BlockIndex];
+ m_TotalSize.fetch_sub(BlockFile->FileSize(), std::memory_order::relaxed);
m_ChunkBlocks.erase(BlockIndex);
ZEN_DEBUG("marking block store file '{}' for delete, block #{}", BlockFile->GetPath(), BlockIndex);
BlockFile->MarkAsDeleteOnClose();
@@ -354,22 +354,31 @@ BlockStore::TryGetChunk(const BlockStoreLocation& Location) const
}
void
-BlockStore::Flush()
+BlockStore::Flush(bool ForceNewBlock)
{
ZEN_TRACE_CPU("BlockStore::Flush");
- RwLock::ExclusiveLockScope _(m_InsertLock);
- if (m_CurrentInsertOffset > 0)
+ if (ForceNewBlock)
{
- uint32_t WriteBlockIndex = m_WriteBlockIndex.load(std::memory_order_acquire);
- WriteBlockIndex = (WriteBlockIndex + 1) & (m_MaxBlockCount - 1);
- if (m_WriteBlock)
+ RwLock::ExclusiveLockScope _(m_InsertLock);
+ if (m_CurrentInsertOffset > 0)
{
- m_WriteBlock->Flush();
+ uint32_t WriteBlockIndex = m_WriteBlockIndex.load(std::memory_order_acquire);
+ WriteBlockIndex = (WriteBlockIndex + 1) & (m_MaxBlockCount - 1);
+ if (m_WriteBlock)
+ {
+ m_WriteBlock->Flush();
+ }
+ m_WriteBlock = nullptr;
+ m_WriteBlockIndex.store(WriteBlockIndex, std::memory_order_release);
+ m_CurrentInsertOffset = 0;
}
- m_WriteBlock = nullptr;
- m_WriteBlockIndex.store(WriteBlockIndex, std::memory_order_release);
- m_CurrentInsertOffset = 0;
+ return;
+ }
+ RwLock::SharedLockScope _(m_InsertLock);
+ if (m_WriteBlock)
+ {
+ m_WriteBlock->Flush();
}
}
@@ -449,11 +458,6 @@ BlockStore::ReclaimSpace(const ReclaimSnapshotState& Snapshot,
{
const BlockStoreLocation& Location = ChunkLocations[Index];
OldTotalSize += Location.Size;
- if (Snapshot.m_ActiveWriteBlocks.contains(Location.BlockIndex))
- {
- continue;
- }
-
auto BlockIndexPtr = BlockIndexToChunkMapIndex.find(Location.BlockIndex);
size_t ChunkMapIndex = 0;
if (BlockIndexPtr == BlockIndexToChunkMapIndex.end())
@@ -524,9 +528,12 @@ BlockStore::ReclaimSpace(const ReclaimSnapshotState& Snapshot,
uint32_t NewBlockIndex = 0;
for (uint32_t BlockIndex : BlocksToReWrite)
{
+ bool IsActiveWriteBlock = Snapshot.m_ActiveWriteBlocks.contains(BlockIndex);
+
const size_t ChunkMapIndex = BlockIndexToChunkMapIndex[BlockIndex];
Ref<BlockStoreFile> OldBlockFile;
+ if (!IsActiveWriteBlock)
{
RwLock::SharedLockScope _i(m_InsertLock);
Stopwatch Timer;
@@ -553,6 +560,7 @@ BlockStore::ReclaimSpace(const ReclaimSnapshotState& Snapshot,
}
ChangeCallback({}, DeleteMap);
DeletedCount += DeleteMap.size();
+ if (OldBlockFile)
{
RwLock::ExclusiveLockScope _i(m_InsertLock);
Stopwatch Timer;
@@ -561,18 +569,15 @@ BlockStore::ReclaimSpace(const ReclaimSnapshotState& Snapshot,
ReadBlockTimeUs += ElapsedUs;
ReadBlockLongestTimeUs = std::max(ElapsedUs, ReadBlockLongestTimeUs);
});
- if (OldBlockFile)
- {
- ZEN_DEBUG("marking cas block store file '{}' for delete, block #{}", OldBlockFile->GetPath(), BlockIndex);
- ZEN_ASSERT(m_ChunkBlocks[BlockIndex] == OldBlockFile);
- m_ChunkBlocks.erase(BlockIndex);
- m_TotalSize.fetch_sub(OldBlockFile->FileSize(), std::memory_order::relaxed);
- OldBlockFile->MarkAsDeleteOnClose();
- }
+ ZEN_DEBUG("marking cas block store file '{}' for delete, block #{}", OldBlockFile->GetPath(), BlockIndex);
+ ZEN_ASSERT(m_ChunkBlocks[BlockIndex] == OldBlockFile);
+ m_ChunkBlocks.erase(BlockIndex);
+ m_TotalSize.fetch_sub(OldBlockFile->FileSize(), std::memory_order::relaxed);
+ OldBlockFile->MarkAsDeleteOnClose();
}
continue;
}
- else if (!OldBlockFile)
+ else if (!OldBlockFile && !IsActiveWriteBlock)
{
// If the block file pointed to does not exist, move any keep chunk them to deleted list
ZEN_ERROR("Expected to find block {} in {} - this should never happen, marking {} entries as deleted.",
@@ -585,6 +590,7 @@ BlockStore::ReclaimSpace(const ReclaimSnapshotState& Snapshot,
}
MovedChunksArray MovedChunks;
+ if (OldBlockFile)
{
ZEN_TRACE_CPU("BlockStore::ReclaimSpace::MoveBlock");
std::vector<uint8_t> Chunk;
@@ -689,9 +695,11 @@ BlockStore::ReclaimSpace(const ReclaimSnapshotState& Snapshot,
}
ChangeCallback(MovedChunks, DeleteMap);
- MovedCount += KeepMap.size();
+ MovedCount += MovedChunks.size();
DeletedCount += DeleteMap.size();
MovedChunks.clear();
+
+ if (OldBlockFile)
{
RwLock::ExclusiveLockScope __(m_InsertLock);
Stopwatch Timer;
@@ -700,14 +708,12 @@ BlockStore::ReclaimSpace(const ReclaimSnapshotState& Snapshot,
ReadBlockTimeUs += ElapsedUs;
ReadBlockLongestTimeUs = std::max(ElapsedUs, ReadBlockLongestTimeUs);
});
- if (OldBlockFile)
- {
- ZEN_DEBUG("marking cas block store file '{}' for delete, block #{}", OldBlockFile->GetPath(), BlockIndex);
- ZEN_ASSERT(m_ChunkBlocks[BlockIndex] == OldBlockFile);
- m_ChunkBlocks.erase(BlockIndex);
- m_TotalSize.fetch_sub(OldBlockFile->FileSize(), std::memory_order::relaxed);
- OldBlockFile->MarkAsDeleteOnClose();
- }
+
+ ZEN_DEBUG("marking cas block store file '{}' for delete, block #{}", OldBlockFile->GetPath(), BlockIndex);
+ ZEN_ASSERT(m_ChunkBlocks[BlockIndex] == OldBlockFile);
+ m_ChunkBlocks.erase(BlockIndex);
+ m_TotalSize.fetch_sub(OldBlockFile->FileSize(), std::memory_order::relaxed);
+ OldBlockFile->MarkAsDeleteOnClose();
}
}
if (NewBlockFile)
@@ -1117,7 +1123,7 @@ TEST_CASE("blockstore.clean.stray.blocks")
CHECK(GetDirectoryContent(RootDirectory / "store", true, false).size() == 1);
}
-TEST_CASE("blockstore.flush.forces.new.block")
+TEST_CASE("blockstore.flush.force.new.block")
{
using namespace blockstore::impl;
@@ -1129,10 +1135,10 @@ TEST_CASE("blockstore.flush.forces.new.block")
std::string FirstChunkData = "This is the data of the first chunk that we will write";
WriteStringAsChunk(Store, FirstChunkData, 4);
- Store.Flush();
+ Store.Flush(/*ForceNewBlock*/ true);
std::string SecondChunkData = "This is the data for the second chunk that we will write";
WriteStringAsChunk(Store, SecondChunkData, 4);
- Store.Flush();
+ Store.Flush(/*ForceNewBlock*/ true);
std::string ThirdChunkData =
"This is a much longer string that will not fit in the first block so it should be placed in the second block";
WriteStringAsChunk(Store, ThirdChunkData, 4);
@@ -1157,7 +1163,7 @@ TEST_CASE("blockstore.iterate.chunks")
std::string SecondChunkData = "This is the data for the second chunk that we will write";
BlockStoreLocation SecondChunkLocation = WriteStringAsChunk(Store, SecondChunkData, 4);
- Store.Flush();
+ Store.Flush(/*ForceNewBlock*/ false);
std::string VeryLargeChunk(ScrubSmallChunkWindowSize * 2, 'L');
BlockStoreLocation VeryLargeChunkLocation = WriteStringAsChunk(Store, VeryLargeChunk, 4);
@@ -1267,7 +1273,7 @@ TEST_CASE("blockstore.reclaim.space")
ChunksToKeep.push_back(ChunkIndex);
}
- Store.Flush();
+ Store.Flush(/*ForceNewBlock*/ false);
BlockStore::ReclaimSnapshotState State1 = Store.GetReclaimSnapshotState();
Store.ReclaimSpace(State1, ChunkLocations, ChunksToKeep, Alignment, true);