Skip to content

Commit

Permalink
Merge pull request #543 from evoskuil/master
Browse files Browse the repository at this point in the history
Optimize set_strong using new hashmap::put(ptr,...).
  • Loading branch information
evoskuil authored Jan 23, 2025
2 parents 7466b06 + 28043d5 commit d6a4edc
Show file tree
Hide file tree
Showing 12 changed files with 705 additions and 450 deletions.
110 changes: 69 additions & 41 deletions include/bitcoin/database/impl/primitives/hashmap.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -199,30 +199,29 @@ bool CLASS::get(const Link& link, Element& element) const NOEXCEPT
// static
TEMPLATE
template <typename Element, if_equal<Element::size, Size>>
bool CLASS::get(const iterator& it, Element& element) NOEXCEPT
bool CLASS::get(const memory_ptr& ptr, const Link& link,
Element& element) NOEXCEPT
{
// This override avoids deadlock when holding iterator to the same table.
return read(it.get(), it.self(), element);
return read(ptr, link, element);
}

// static
TEMPLATE
template <typename Element, if_equal<Element::size, Size>>
bool CLASS::get(const iterator& it, const Link& link,
Element& element) NOEXCEPT
bool CLASS::get(const iterator& it, Element& element) NOEXCEPT
{
// This override avoids deadlock when holding iterator to the same table.
return read(it.get(), link, element);
return read(it.get(), it.self(), element);
}

// static
TEMPLATE
template <typename Element, if_equal<Element::size, Size>>
bool CLASS::get(const memory_ptr& ptr, const Link& link,
bool CLASS::get(const iterator& it, const Link& link,
Element& element) NOEXCEPT
{
// This override avoids deadlock when holding iterator to the same table.
return read(ptr, link, element);
return read(it.get(), link, element);
}

TEMPLATE
Expand Down Expand Up @@ -307,24 +306,16 @@ template <typename Element, if_equal<Element::size, Size>>
bool CLASS::put(const Link& link, const Key& key,
const Element& element) NOEXCEPT
{
using namespace system;
const auto ptr = body_.get(link);
if (!ptr)
return false;

// iostream.flush is a nop (direct copy).
iostream stream{ *ptr };
finalizer sink{ stream };
sink.skip_bytes(Link::size);
sink.write_bytes(key);

if constexpr (!is_slab)
{
BC_DEBUG_ONLY(sink.set_limit(Size * element.count());)
}
// This override is the normal form.
return write(get_memory(), link, key, element);
}

auto& next = unsafe_array_cast<uint8_t, Link::size>(ptr->begin());
return element.to_data(sink) && head_.push(link, next, head_.index(key));
TEMPLATE
template <typename Element, if_equal<Element::size, Size>>
bool CLASS::put(const memory_ptr& ptr, const Link& link, const Key& key,
const Element& element) NOEXCEPT
{
return write(ptr, link, key, element);
}

TEMPLATE
Expand Down Expand Up @@ -355,6 +346,31 @@ Link CLASS::commit_link(const Link& link, const Key& key) NOEXCEPT
// protected/static
// ----------------------------------------------------------------------------

TEMPLATE
Link CLASS::first(const memory_ptr& ptr, Link link, const Key& key) NOEXCEPT
{
if (!ptr)
return {};

while (!link.is_terminal())
{
// get element offset (fault)
const auto offset = ptr->offset(body::link_to_position(link));
if (is_null(offset))
return {};

// element key matches (found)
if (is_zero(std::memcmp(key.data(), std::next(offset, Link::size),
array_count<Key>)))
return link;

// set next element link (loop)
link = system::unsafe_array_cast<uint8_t, Link::size>(offset);
}

return link;
}

TEMPLATE
template <typename Element, if_equal<Element::size, Size>>
bool CLASS::read(const memory_ptr& ptr, const Link& link,
Expand Down Expand Up @@ -387,28 +403,40 @@ bool CLASS::read(const memory_ptr& ptr, const Link& link,
}

TEMPLATE
Link CLASS::first(const memory_ptr& ptr, Link link, const Key& key) NOEXCEPT
template <typename Element, if_equal<Element::size, Size>>
bool CLASS::write(const memory_ptr& ptr, const Link& link, const Key& key,
const Element& element) NOEXCEPT
{
if (!ptr)
return {};
if (!ptr || link.is_terminal())
return false;

while (!link.is_terminal())
{
// get element offset (fault)
const auto offset = ptr->offset(body::link_to_position(link));
if (is_null(offset))
return {};
using namespace system;
const auto start = body::link_to_position(link);
if (is_limited<ptrdiff_t>(start))
return false;

// element key matches (found)
if (is_zero(std::memcmp(key.data(), std::next(offset, Link::size),
array_count<Key>)))
return link;
const auto size = ptr->size();
const auto position = possible_narrow_and_sign_cast<ptrdiff_t>(start);
if (position > size)
return false;

// set next element link (loop)
link = system::unsafe_array_cast<uint8_t, Link::size>(offset);
const auto offset = ptr->offset(position);
if (is_null(offset))
return false;

// iostream.flush is a nop (direct copy).
iostream stream{ offset, size - position };
finalizer sink{ stream };
sink.skip_bytes(Link::size);
sink.write_bytes(key);

if constexpr (!is_slab)
{
BC_DEBUG_ONLY(sink.set_limit(Size * element.count());)
}

return link;
auto& next = unsafe_array_cast<uint8_t, Link::size>(ptr->begin());
return element.to_data(sink) && head_.push(link, next, head_.index(key));
}

} // namespace database
Expand Down
19 changes: 17 additions & 2 deletions include/bitcoin/database/impl/primitives/linkage.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,36 @@ inline CLASS::linkage(const bytes& other) NOEXCEPT
}

TEMPLATE
constexpr linkage<Size>& CLASS::operator=(integer other) NOEXCEPT
constexpr CLASS& CLASS::operator=(integer other) NOEXCEPT
{
value = other;
return *this;
}

TEMPLATE
inline linkage<Size>& CLASS::operator=(const bytes& other) NOEXCEPT
inline CLASS& CLASS::operator=(const bytes& other) NOEXCEPT
{
value = 0;
system::unsafe_array_cast<uint8_t, Size>(&value) = other;
value = system::native_from_little_end(value);
return *this;
}

TEMPLATE
inline CLASS& CLASS::operator++() NOEXCEPT
{
++value;
return *this;
}

TEMPLATE
inline CLASS CLASS::operator++(int) NOEXCEPT
{
auto self = *this;
++(*this);
return self;
}

////TEMPLATE
////constexpr CLASS::operator bool() const NOEXCEPT
////{
Expand Down
Loading

0 comments on commit d6a4edc

Please sign in to comment.