From 66cd99b0ff4803c69326ffa85d0968d102c1bb28 Mon Sep 17 00:00:00 2001 From: Sebastian Messmer Date: Thu, 8 Oct 2015 01:19:44 +0200 Subject: [PATCH] Use hinted linear search instead of binary search --- .../fsblobstore/utils/DirEntryList.cpp | 38 ++++++++++++++++--- .../fsblobstore/utils/DirEntryList.h | 3 ++ 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/filesystem/fsblobstore/utils/DirEntryList.cpp b/src/filesystem/fsblobstore/utils/DirEntryList.cpp index b1cd0e12..1170d383 100644 --- a/src/filesystem/fsblobstore/utils/DirEntryList.cpp +++ b/src/filesystem/fsblobstore/utils/DirEntryList.cpp @@ -1,4 +1,5 @@ #include "DirEntryList.h" +#include //TODO Get rid of that in favor of better error handling #include @@ -52,9 +53,7 @@ void DirEntryList::add(const string &name, const Key &blobKey, fspp::Dir::EntryT if (_hasChild(name)) { throw fspp::fuse::FuseErrnoException(EEXIST); } - auto insert_pos = std::upper_bound(_entries.begin(), _entries.end(), blobKey, [] (const Key &key, const DirEntry &item) { - return std::less()(key, item.key); - }); + auto insert_pos = _findUpperBound(blobKey); _entries.emplace(insert_pos, entryType, name, blobKey, mode, uid, gid); } @@ -78,15 +77,42 @@ void DirEntryList::remove(const Key &key) { } vector::iterator DirEntryList::_find(const Key &key) { - auto found = std::lower_bound(_entries.begin(), _entries.end(), key, [] (const DirEntry &entry, const Key &key) { - return std::less()(entry.key, key); - }); + auto found = _findLowerBound(key); if (found == _entries.end() || found->key != key) { throw fspp::fuse::FuseErrnoException(ENOENT); } return found; } +vector::iterator DirEntryList::_findLowerBound(const Key &key) { + return _findFirst(key, [&key] (const DirEntry &entry) { + return !std::less()(entry.key, key); + }); +} + +vector::iterator DirEntryList::_findUpperBound(const Key &key) { + return _findFirst(key, [&key] (const DirEntry &entry) { + return std::less()(key, entry.key); + }); +} + +vector::iterator DirEntryList::_findFirst(const Key &hint, std::function pred) { + //TODO Factor out a datastructure that keeps a sorted std::vector and allows these _findLowerBound()/_findUpperBound operations using this hinted linear search + if (_entries.size() == 0) { + return _entries.end(); + } + double startpos_percent = static_cast(*static_cast(hint.data())) / std::numeric_limits::max(); + auto iter = _entries.begin() + static_cast(startpos_percent * (_entries.size()-1)); + ASSERT(iter >= _entries.begin() && iter < _entries.end(), "Startpos out of range"); + while(iter != _entries.begin() && pred(*iter)) { + --iter; + } + while(iter != _entries.end() && !pred(*iter)) { + ++iter; + } + return iter; +} + vector::const_iterator DirEntryList::_find(const Key &key) const { return const_cast(this)->_find(key); } diff --git a/src/filesystem/fsblobstore/utils/DirEntryList.h b/src/filesystem/fsblobstore/utils/DirEntryList.h index f45d637b..c7d258b1 100644 --- a/src/filesystem/fsblobstore/utils/DirEntryList.h +++ b/src/filesystem/fsblobstore/utils/DirEntryList.h @@ -37,6 +37,9 @@ namespace cryfs { bool _hasChild(const std::string &name) const; std::vector::iterator _find(const blockstore::Key &key); std::vector::const_iterator _find(const blockstore::Key &key) const; + std::vector::iterator _findUpperBound(const blockstore::Key &key); + std::vector::iterator _findLowerBound(const blockstore::Key &key); + std::vector::iterator _findFirst(const blockstore::Key &hint, std::function pred); std::vector _entries;