aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2025-05-07 10:23:42 +0200
committerGitHub Enterprise <[email protected]>2025-05-07 10:23:42 +0200
commit68938614c95635045a394ff0a52786b82f01ffc4 (patch)
tree6193f85d4fe3ec154e78bb494b979a91733f9ae6 /src
parentadded logic to handle empty directories correctly (#383) (diff)
downloadzen-68938614c95635045a394ff0a52786b82f01ffc4.tar.xz
zen-68938614c95635045a394ff0a52786b82f01ffc4.zip
optimize block store CompactBlocks (#384)
- Improvement: Optimize block compact reducing memcpy operations - Improvement: Handle padding of block store blocks when compacting to avoid excessive flusing of write buffer - Improvement: Handle padding when writing oplog index snapshot to avoid unnecessary flushing of write buffer
Diffstat (limited to 'src')
-rw-r--r--src/zencore/basicfile.cpp29
-rw-r--r--src/zencore/include/zencore/basicfile.h8
-rw-r--r--src/zenserver/projectstore/projectstore.cpp24
-rw-r--r--src/zenstore/blockstore.cpp33
4 files changed, 61 insertions, 33 deletions
diff --git a/src/zencore/basicfile.cpp b/src/zencore/basicfile.cpp
index ea526399c..12ee26155 100644
--- a/src/zencore/basicfile.cpp
+++ b/src/zencore/basicfile.cpp
@@ -792,6 +792,35 @@ BasicFileWriter::~BasicFileWriter()
}
void
+BasicFileWriter::AddPadding(uint64_t Padding)
+{
+ while (Padding)
+ {
+ const uint64_t BufferOffset = m_BufferEnd - m_BufferStart;
+ const uint64_t RemainingBufferCapacity = m_BufferSize - BufferOffset;
+ const uint64_t BlockPadBytes = Min(RemainingBufferCapacity, Padding);
+
+ memset(m_Buffer + BufferOffset, 0, BlockPadBytes);
+ m_BufferEnd += BlockPadBytes;
+ Padding -= BlockPadBytes;
+
+ if ((BufferOffset + BlockPadBytes) == m_BufferSize)
+ {
+ Flush();
+ }
+ }
+}
+
+uint64_t
+BasicFileWriter::AlignTo(uint64_t Alignment)
+{
+ uint64_t AlignedPos = RoundUp(m_BufferEnd, Alignment);
+ uint64_t Padding = AlignedPos - m_BufferEnd;
+ AddPadding(Padding);
+ return AlignedPos;
+}
+
+void
BasicFileWriter::Write(const void* Data, uint64_t Size, uint64_t FileOffset)
{
if (m_Buffer == nullptr || (Size >= m_BufferSize))
diff --git a/src/zencore/include/zencore/basicfile.h b/src/zencore/include/zencore/basicfile.h
index 57798b6f4..465499d2b 100644
--- a/src/zencore/include/zencore/basicfile.h
+++ b/src/zencore/include/zencore/basicfile.h
@@ -174,9 +174,11 @@ public:
BasicFileWriter(BasicFile& Base, uint64_t BufferSize);
~BasicFileWriter();
- void Write(const void* Data, uint64_t Size, uint64_t FileOffset);
- void Write(const CompositeBuffer& Data, uint64_t FileOffset);
- void Flush();
+ void Write(const void* Data, uint64_t Size, uint64_t FileOffset);
+ void Write(const CompositeBuffer& Data, uint64_t FileOffset);
+ void AddPadding(uint64_t Padding);
+ uint64_t AlignTo(uint64_t Alignment);
+ void Flush();
private:
BasicFile& m_Base;
diff --git a/src/zenserver/projectstore/projectstore.cpp b/src/zenserver/projectstore/projectstore.cpp
index e91e6ac51..071aab137 100644
--- a/src/zenserver/projectstore/projectstore.cpp
+++ b/src/zenserver/projectstore/projectstore.cpp
@@ -1748,36 +1748,28 @@ ProjectStore::Oplog::WriteIndexSnapshot()
uint64_t Offset = 0;
IndexFile.Write(&Header, sizeof(OplogIndexHeader), Offset);
- Offset += sizeof(OplogIndexHeader);
- Offset = RoundUp(Offset, OplogIndexHeader::DataAlignment);
+ Offset = IndexFile.AlignTo(OplogIndexHeader::DataAlignment);
IndexFile.Write(LSNEntries.data(), LSNEntries.size() * sizeof(uint32_t), Offset);
- Offset += LSNEntries.size() * sizeof(uint32_t);
- Offset = RoundUp(Offset, OplogIndexHeader::DataAlignment);
+ Offset = IndexFile.AlignTo(OplogIndexHeader::DataAlignment);
IndexFile.Write(Keys.data(), Keys.size() * sizeof(Oid), Offset);
- Offset += Keys.size() * sizeof(Oid);
- Offset = RoundUp(Offset, OplogIndexHeader::DataAlignment);
+ Offset = IndexFile.AlignTo(OplogIndexHeader::DataAlignment);
IndexFile.Write(AddressMapEntries.data(), AddressMapEntries.size() * sizeof(OplogEntryAddress), Offset);
- Offset += AddressMapEntries.size() * sizeof(OplogEntryAddress);
- Offset = RoundUp(Offset, OplogIndexHeader::DataAlignment);
+ Offset = IndexFile.AlignTo(OplogIndexHeader::DataAlignment);
IndexFile.Write(LatestOpMapEntries.data(), LatestOpMapEntries.size() * sizeof(uint32_t), Offset);
- Offset += LatestOpMapEntries.size() * sizeof(uint32_t);
- Offset = RoundUp(Offset, OplogIndexHeader::DataAlignment);
+ Offset = IndexFile.AlignTo(OplogIndexHeader::DataAlignment);
IndexFile.Write(ChunkMapEntries.data(), ChunkMapEntries.size() * sizeof(IoHash), Offset);
- Offset += ChunkMapEntries.size() * sizeof(IoHash);
- Offset = RoundUp(Offset, OplogIndexHeader::DataAlignment);
+ Offset = IndexFile.AlignTo(OplogIndexHeader::DataAlignment);
IndexFile.Write(MetaMapEntries.data(), MetaMapEntries.size() * sizeof(IoHash), Offset);
- Offset += MetaMapEntries.size() * sizeof(IoHash);
- Offset = RoundUp(Offset, OplogIndexHeader::DataAlignment);
+ Offset = IndexFile.AlignTo(OplogIndexHeader::DataAlignment);
IndexFile.Write(FilePathLengths.data(), FilePathLengths.size() * sizeof(uint32_t), Offset);
- Offset += FilePathLengths.size() * sizeof(uint32_t);
- Offset = RoundUp(Offset, OplogIndexHeader::DataAlignment);
+ Offset = IndexFile.AlignTo(OplogIndexHeader::DataAlignment);
for (const auto& FilePath : FilePaths)
{
diff --git a/src/zenstore/blockstore.cpp b/src/zenstore/blockstore.cpp
index c58080e6a..e0f371061 100644
--- a/src/zenstore/blockstore.cpp
+++ b/src/zenstore/blockstore.cpp
@@ -1062,11 +1062,10 @@ BlockStore::CompactBlocks(const BlockStoreCompactState& CompactState,
std::sort(SortedChunkIndexes.begin(), SortedChunkIndexes.end(), [&ChunkLocations](size_t Lhs, size_t Rhs) {
return ChunkLocations[Lhs].Offset < ChunkLocations[Rhs].Offset;
});
- BasicFileBuffer SourceFileBuffer(OldBlockFile->GetBasicFile(), Min(65536u, OldBlockSize));
+ BasicFileBuffer SourceFileBuffer(OldBlockFile->GetBasicFile(), Min(256u * 1024u, OldBlockSize));
- uint64_t WrittenBytesToBlock = 0;
- uint64_t MovedFromBlock = 0;
- std::vector<uint8_t> Chunk;
+ uint64_t MovedFromBlock = 0;
+ std::vector<uint8_t> ChunkBuffer;
for (const size_t& ChunkIndex : SortedChunkIndexes)
{
const BlockStoreLocation ChunkLocation = ChunkLocations[ChunkIndex];
@@ -1084,10 +1083,15 @@ BlockStore::CompactBlocks(const BlockStoreCompactState& CompactState,
continue;
}
- Chunk.resize(ChunkLocation.Size);
- SourceFileBuffer.Read(Chunk.data(), Chunk.size(), ChunkLocation.Offset);
+ MemoryView ChunkView = SourceFileBuffer.MakeView(ChunkLocation.Size, ChunkLocation.Offset);
+ if (ChunkView.GetSize() != ChunkLocation.Size)
+ {
+ ChunkBuffer.resize(ChunkLocation.Size);
+ SourceFileBuffer.Read(ChunkBuffer.data(), ChunkLocation.Size, ChunkLocation.Offset);
+ ChunkView = MemoryView(ChunkBuffer.data(), ChunkLocation.Size);
+ }
- if ((WriteOffset + Chunk.size()) > m_MaxBlockSize)
+ if ((WriteOffset + ChunkView.GetSize()) > m_MaxBlockSize)
{
TargetFileBuffer.reset();
if (NewBlockFile)
@@ -1174,20 +1178,21 @@ BlockStore::CompactBlocks(const BlockStoreCompactState& CompactState,
NewBlockFile->Create(m_MaxBlockSize);
NewBlockIndex = NextBlockIndex;
WriteOffset = 0;
- AddedSize += WrittenBytesToBlock;
- WrittenBytesToBlock = 0;
- TargetFileBuffer = std::make_unique<BasicFileWriter>(NewBlockFile->GetBasicFile(), Min(65536u, m_MaxBlockSize));
+ AddedSize += WriteOffset;
+ WriteOffset = 0;
+ TargetFileBuffer = std::make_unique<BasicFileWriter>(NewBlockFile->GetBasicFile(), Min(256u * 1024u, m_MaxBlockSize));
}
- TargetFileBuffer->Write(Chunk.data(), ChunkLocation.Size, WriteOffset);
+ WriteOffset = TargetFileBuffer->AlignTo(PayloadAlignment);
+
+ TargetFileBuffer->Write(ChunkView.GetData(), ChunkLocation.Size, WriteOffset);
MovedChunks.push_back(
{ChunkIndex, {.BlockIndex = NewBlockIndex, .Offset = gsl::narrow<uint32_t>(WriteOffset), .Size = ChunkLocation.Size}});
- WrittenBytesToBlock = WriteOffset + ChunkLocation.Size;
+ WriteOffset += ChunkLocation.Size;
MovedFromBlock += RoundUp(ChunkLocation.Offset + ChunkLocation.Size, PayloadAlignment) - ChunkLocation.Offset;
- WriteOffset = RoundUp(WriteOffset + ChunkLocation.Size, PayloadAlignment);
}
- AddedSize += WrittenBytesToBlock;
+ AddedSize += WriteOffset;
ZEN_INFO("{}moved {} chunks ({}) from '{}' to new block, freeing {}",
LogPrefix,
KeepChunkIndexes.size(),