From 7e54d284e1b8d99d63304a5075a4597aa4787a8d Mon Sep 17 00:00:00 2001 From: Sebastian Messmer Date: Mon, 5 Oct 2015 02:55:04 +0200 Subject: [PATCH] Speed up writing back of DirBlobs by another factor of 3 (so 9 in total) by serializing the whole blob and writing it back with one write() call --- src/filesystem/fsblobstore/DirBlob.cpp | 42 ++++++++++++++------------ src/filesystem/fsblobstore/DirBlob.h | 4 +-- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/src/filesystem/fsblobstore/DirBlob.cpp b/src/filesystem/fsblobstore/DirBlob.cpp index cbb22273..a3a3f14a 100644 --- a/src/filesystem/fsblobstore/DirBlob.cpp +++ b/src/filesystem/fsblobstore/DirBlob.cpp @@ -47,47 +47,51 @@ unique_ref DirBlob::InitializeEmptyDir(unique_ref blob, std::func return make_unique_ref(std::move(blob), getLstatSize); } -Data DirBlob::_writeEntry(const DirBlob::Entry & entry) { +size_t DirBlob::_serializedSizeOfEntry(const DirBlob::Entry &entry) { + return 1 + (entry.name.size() + 1) + (entry.key.STRING_LENGTH + 1) + sizeof(uid_t) + sizeof(gid_t) + sizeof(mode_t); +} + +void DirBlob::_serializeEntry(const DirBlob::Entry & entry, uint8_t *dest) { + //TODO Write key as binary? string keystr = entry.key.ToString(); - unsigned int size = 1 + (entry.name.size() + 1) + (keystr.size() + 1) + sizeof(uid_t) + sizeof(gid_t) + sizeof(mode_t); - Data result(size); unsigned int offset = 0; - - *static_cast(result.dataOffset(offset)) = static_cast(entry.type); + *(dest+offset) = static_cast(entry.type); offset += 1; - std::memcpy(result.dataOffset(offset), entry.name.c_str(), entry.name.size()+1); + std::memcpy(dest+offset, entry.name.c_str(), entry.name.size()+1); offset += entry.name.size() + 1; - std::memcpy(result.dataOffset(offset), keystr.c_str(), keystr.size() + 1); + std::memcpy(dest+offset, keystr.c_str(), keystr.size() + 1); offset += keystr.size() + 1; - *reinterpret_cast(result.dataOffset(offset)) = entry.uid; + *reinterpret_cast(dest+offset) = entry.uid; offset += sizeof(uid_t); - *reinterpret_cast(result.dataOffset(offset)) = entry.gid; + *reinterpret_cast(dest+offset) = entry.gid; offset += sizeof(gid_t); - *reinterpret_cast(result.dataOffset(offset)) = entry.mode; + *reinterpret_cast(dest+offset) = entry.mode; offset += sizeof(mode_t); - ASSERT(offset == size, "Didn't write correct number of elements"); - - return result; + ASSERT(offset == _serializedSizeOfEntry(entry), "Didn't write correct number of elements"); } void DirBlob::_writeEntriesToBlob() { std::unique_lock lock(_mutex); if (_changed) { - //TODO Resizing is imperformant - baseBlob().resize(1); - unsigned int offset = 1; + size_t serializedSize = 0; for (const auto &entry : _entries) { - Data serializedEntry = _writeEntry(entry); - baseBlob().write(serializedEntry.data(), offset, serializedEntry.size()); - offset += serializedEntry.size(); + serializedSize += _serializedSizeOfEntry(entry); } + Data serialized(serializedSize); + unsigned int offset = 0; + for (const auto &entry : _entries) { + _serializeEntry(entry, static_cast(serialized.dataOffset(offset))); + offset += _serializedSizeOfEntry(entry); + } + baseBlob().resize(1 + serializedSize); + baseBlob().write(serialized.data(), 1, serializedSize); _changed = false; } } diff --git a/src/filesystem/fsblobstore/DirBlob.h b/src/filesystem/fsblobstore/DirBlob.h index 2c605cc7..2d643587 100644 --- a/src/filesystem/fsblobstore/DirBlob.h +++ b/src/filesystem/fsblobstore/DirBlob.h @@ -4,7 +4,6 @@ #include #include -#include #include #include "FsBlob.h" #include @@ -91,7 +90,8 @@ namespace cryfs { void _readEntriesFromBlob(); void _writeEntriesToBlob(); - static cpputils::Data _writeEntry(const DirBlob::Entry & entry); + static size_t _serializedSizeOfEntry(const DirBlob::Entry &entry); + static void _serializeEntry(const DirBlob::Entry &entry, uint8_t *dest); std::vector::iterator _findChild(const blockstore::Key &key);