Skip to content

Commit

Permalink
BlobRoute : Comparison and Hash can be made much cheaper without stri…
Browse files Browse the repository at this point in the history
…ng formatting. (#66)

* Comparison and Hash can be made much cheaper without string formatting.

* Remove magic numbers

* Lift shard_mask

* Uplift make_new_shard_id

* Use boost::hash_value
  • Loading branch information
szmyd authored Sep 21, 2023
1 parent 1efd36d commit b5cc370
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 51 deletions.
41 changes: 41 additions & 0 deletions src/lib/blob_route.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <functional>

#include <boost/functional/hash.hpp>

#include "homeobject/common.hpp"

namespace homeobject {

///
// A Key used in the IndexService (BTree). The inclusion of Shard allows BlobRoutes
// to appear in a different Index should the Blob (Shard) be moved between Pgs.
struct BlobRoute {
shard_id shard;
blob_id blob;
auto operator<=>(BlobRoute const&) const = default;
};

} // namespace homeobject

namespace fmt {
template <>
struct formatter< homeobject::BlobRoute > {
template < typename ParseContext >
constexpr auto parse(ParseContext& ctx) {
return ctx.begin();
}

template < typename FormatContext >
auto format(homeobject::BlobRoute const& r, FormatContext& ctx) {
return format_to(ctx.out(), "{:04x}:{:012x}:{:016x}", (r.shard >> homeobject::shard_width),
(r.shard & homeobject::shard_mask), r.blob);
}
};
} // namespace fmt

template <>
struct std::hash< homeobject::BlobRoute > {
std::size_t operator()(homeobject::BlobRoute const& r) const noexcept {
return boost::hash_value< homeobject::blob_id >(std::make_pair(r.shard, r.blob));
}
};
6 changes: 6 additions & 0 deletions src/lib/homeobject_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ class ReplicationService;

namespace homeobject {

constexpr size_t pg_width = sizeof(pg_id) * 8;
constexpr size_t shard_width = (sizeof(shard_id) * 8) - pg_width;
constexpr size_t shard_mask = std::numeric_limits< homeobject::shard_id >::max() >> pg_width;

inline shard_id make_new_shard_id(pg_id pg, shard_id next_shard) { return ((uint64_t)pg << shard_width) | next_shard; }

inline bool operator<(ShardInfo const& lhs, ShardInfo const& rhs) { return lhs.id < rhs.id; }
inline bool operator==(ShardInfo const& lhs, ShardInfo const& rhs) { return lhs.id == rhs.id; }

Expand Down
1 change: 0 additions & 1 deletion src/lib/homestore/homeobject.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ class HSHomeObject : public HomeObjectImpl {

private:
shard_id generate_new_shard_id(pg_id pg);
shard_id make_new_shard_id(pg_id pg, uint64_t sequence_num) const;
uint64_t get_sequence_num_from_shard_id(uint64_t shard_id);
std::string serialize_shard(const Shard& shard) const;
Shard deserialize_shard(const std::string& shard_info_str) const;
Expand Down
11 changes: 3 additions & 8 deletions src/lib/homestore/shard_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,9 @@

namespace homeobject {

static constexpr uint32_t SEQUENCE_BIT_NUM_IN_SHARD{48};

uint64_t ShardManager::max_shard_size() { return Gi; }

uint64_t ShardManager::max_shard_num_in_pg() { return ((uint64_t)0x01) << SEQUENCE_BIT_NUM_IN_SHARD; }
uint64_t ShardManager::max_shard_num_in_pg() { return ((uint64_t)0x01) << shard_width; }

shard_id HSHomeObject::generate_new_shard_id(pg_id pg) {
std::scoped_lock lock_guard(_pg_lock);
Expand All @@ -23,10 +21,6 @@ shard_id HSHomeObject::generate_new_shard_id(pg_id pg) {
return make_new_shard_id(pg, new_sequence_num);
}

shard_id HSHomeObject::make_new_shard_id(pg_id pg, uint64_t sequence_num) const {
return ((uint64_t)pg << SEQUENCE_BIT_NUM_IN_SHARD) | sequence_num;
}

uint64_t HSHomeObject::get_sequence_num_from_shard_id(uint64_t shard_id) {
return shard_id & (max_shard_num_in_pg() - 1);
}
Expand Down Expand Up @@ -99,7 +93,8 @@ ShardManager::Result< ShardInfo > HSHomeObject::_create_shard(pg_id pg_owner, ui
replica_set->write(sisl::blob(buf->data_begin(), needed_size), sisl::blob(), value, static_cast< void* >(&p));
auto info = std::move(sf).get();
if (!bool(info)) {
LOGWARN("create new shard [{}] on pg [{}] is failed with error:{}", new_shard_id, pg_owner, info.error());
LOGWARN("create new shard [{}] on pg [{}] is failed with error:{}", new_shard_id & shard_mask, pg_owner,
info.error());
}
header->~ReplicationMessageHeader();
return info;
Expand Down
43 changes: 3 additions & 40 deletions src/lib/memory/homeobject.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,44 +7,9 @@
#include "mocks/repl_service.h"

#include "lib/homeobject_impl.hpp"
#include "lib/blob_route.hpp"

namespace homeobject {
struct BlobRoute {
shard_id shard;
blob_id blob;
};
} // namespace homeobject

namespace fmt {
template <>
struct formatter< homeobject::BlobRoute > {
template < typename ParseContext >
constexpr auto parse(ParseContext& ctx) {
return ctx.begin();
}

template < typename FormatContext >
auto format(const homeobject::BlobRoute& r, FormatContext& ctx) {
return format_to(ctx.out(), "{}:{:012x}", r.shard, r.blob);
}
};
} // namespace fmt

template <>
struct std::hash< homeobject::BlobRoute > {
std::size_t operator()(homeobject::BlobRoute const& r) const noexcept {
return std::hash< std::string >()(fmt::format("{}", r));
}
};

namespace homeobject {

inline bool operator<(BlobRoute const& lhs, BlobRoute const& rhs) {
return fmt::format("{}", lhs) < fmt::format("{}", rhs);
}
inline bool operator==(BlobRoute const& lhs, BlobRoute const& rhs) {
return fmt::format("{}", lhs) == fmt::format("{}", rhs);
}

///
// Used to TombStone Blob's in the Index to defer for GC.
Expand All @@ -55,13 +20,11 @@ struct BlobExt {
Blob* _blob;

explicit operator bool() const { return _state == BlobState::ALIVE; }
bool operator==(const BlobExt& rhs) const { return _blob == rhs._blob; }
};
inline bool operator==(BlobExt const& lhs, BlobExt const& rhs) { return lhs._blob == rhs._blob; }

using btree = folly::ConcurrentHashMap< BlobRoute, BlobExt >;

struct ShardIndex {
btree _btree;
folly::ConcurrentHashMap< BlobRoute, BlobExt > _btree;
std::atomic< blob_id > _shard_seq_num{0ull};
~ShardIndex();
};
Expand Down
4 changes: 2 additions & 2 deletions src/lib/memory/shard_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ ShardManager::Result< ShardInfo > MemoryHomeObject::_create_shard(pg_id pg_owner
if (_pg_map.end() == pg_it) return folly::makeUnexpected(ShardError::UNKNOWN_PG);

auto& s_list = pg_it->second.shards;
info.id = (((uint64_t)pg_owner) << 48) + s_list.size();
info.id = make_new_shard_id(pg_owner, s_list.size());
auto iter = s_list.emplace(s_list.end(), Shard(info));
LOGDEBUG("Creating Shard [{}]: in Pg [{}] of Size [{}b]", info.id, pg_owner, size_bytes);
LOGDEBUG("Creating Shard [{}]: in Pg [{}] of Size [{}b]", info.id & shard_mask, pg_owner, size_bytes);
auto [_, s_happened] = _shard_map.emplace(info.id, iter);
RELEASE_ASSERT(s_happened, "Duplicate Shard insertion!");
}
Expand Down

0 comments on commit b5cc370

Please sign in to comment.