Skip to content

Commit d6a4edc

Browse files
authored
Merge pull request #543 from evoskuil/master
Optimize set_strong using new hashmap::put(ptr,...).
2 parents 7466b06 + 28043d5 commit d6a4edc

File tree

12 files changed

+705
-450
lines changed

12 files changed

+705
-450
lines changed

include/bitcoin/database/impl/primitives/hashmap.ipp

Lines changed: 69 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -199,30 +199,29 @@ bool CLASS::get(const Link& link, Element& element) const NOEXCEPT
199199
// static
200200
TEMPLATE
201201
template <typename Element, if_equal<Element::size, Size>>
202-
bool CLASS::get(const iterator& it, Element& element) NOEXCEPT
202+
bool CLASS::get(const memory_ptr& ptr, const Link& link,
203+
Element& element) NOEXCEPT
203204
{
204-
// This override avoids deadlock when holding iterator to the same table.
205-
return read(it.get(), it.self(), element);
205+
return read(ptr, link, element);
206206
}
207207

208208
// static
209209
TEMPLATE
210210
template <typename Element, if_equal<Element::size, Size>>
211-
bool CLASS::get(const iterator& it, const Link& link,
212-
Element& element) NOEXCEPT
211+
bool CLASS::get(const iterator& it, Element& element) NOEXCEPT
213212
{
214213
// This override avoids deadlock when holding iterator to the same table.
215-
return read(it.get(), link, element);
214+
return read(it.get(), it.self(), element);
216215
}
217216

218217
// static
219218
TEMPLATE
220219
template <typename Element, if_equal<Element::size, Size>>
221-
bool CLASS::get(const memory_ptr& ptr, const Link& link,
220+
bool CLASS::get(const iterator& it, const Link& link,
222221
Element& element) NOEXCEPT
223222
{
224223
// This override avoids deadlock when holding iterator to the same table.
225-
return read(ptr, link, element);
224+
return read(it.get(), link, element);
226225
}
227226

228227
TEMPLATE
@@ -307,24 +306,16 @@ template <typename Element, if_equal<Element::size, Size>>
307306
bool CLASS::put(const Link& link, const Key& key,
308307
const Element& element) NOEXCEPT
309308
{
310-
using namespace system;
311-
const auto ptr = body_.get(link);
312-
if (!ptr)
313-
return false;
314-
315-
// iostream.flush is a nop (direct copy).
316-
iostream stream{ *ptr };
317-
finalizer sink{ stream };
318-
sink.skip_bytes(Link::size);
319-
sink.write_bytes(key);
320-
321-
if constexpr (!is_slab)
322-
{
323-
BC_DEBUG_ONLY(sink.set_limit(Size * element.count());)
324-
}
309+
// This override is the normal form.
310+
return write(get_memory(), link, key, element);
311+
}
325312

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

330321
TEMPLATE
@@ -355,6 +346,31 @@ Link CLASS::commit_link(const Link& link, const Key& key) NOEXCEPT
355346
// protected/static
356347
// ----------------------------------------------------------------------------
357348

349+
TEMPLATE
350+
Link CLASS::first(const memory_ptr& ptr, Link link, const Key& key) NOEXCEPT
351+
{
352+
if (!ptr)
353+
return {};
354+
355+
while (!link.is_terminal())
356+
{
357+
// get element offset (fault)
358+
const auto offset = ptr->offset(body::link_to_position(link));
359+
if (is_null(offset))
360+
return {};
361+
362+
// element key matches (found)
363+
if (is_zero(std::memcmp(key.data(), std::next(offset, Link::size),
364+
array_count<Key>)))
365+
return link;
366+
367+
// set next element link (loop)
368+
link = system::unsafe_array_cast<uint8_t, Link::size>(offset);
369+
}
370+
371+
return link;
372+
}
373+
358374
TEMPLATE
359375
template <typename Element, if_equal<Element::size, Size>>
360376
bool CLASS::read(const memory_ptr& ptr, const Link& link,
@@ -387,28 +403,40 @@ bool CLASS::read(const memory_ptr& ptr, const Link& link,
387403
}
388404

389405
TEMPLATE
390-
Link CLASS::first(const memory_ptr& ptr, Link link, const Key& key) NOEXCEPT
406+
template <typename Element, if_equal<Element::size, Size>>
407+
bool CLASS::write(const memory_ptr& ptr, const Link& link, const Key& key,
408+
const Element& element) NOEXCEPT
391409
{
392-
if (!ptr)
393-
return {};
410+
if (!ptr || link.is_terminal())
411+
return false;
394412

395-
while (!link.is_terminal())
396-
{
397-
// get element offset (fault)
398-
const auto offset = ptr->offset(body::link_to_position(link));
399-
if (is_null(offset))
400-
return {};
413+
using namespace system;
414+
const auto start = body::link_to_position(link);
415+
if (is_limited<ptrdiff_t>(start))
416+
return false;
401417

402-
// element key matches (found)
403-
if (is_zero(std::memcmp(key.data(), std::next(offset, Link::size),
404-
array_count<Key>)))
405-
return link;
418+
const auto size = ptr->size();
419+
const auto position = possible_narrow_and_sign_cast<ptrdiff_t>(start);
420+
if (position > size)
421+
return false;
406422

407-
// set next element link (loop)
408-
link = system::unsafe_array_cast<uint8_t, Link::size>(offset);
423+
const auto offset = ptr->offset(position);
424+
if (is_null(offset))
425+
return false;
426+
427+
// iostream.flush is a nop (direct copy).
428+
iostream stream{ offset, size - position };
429+
finalizer sink{ stream };
430+
sink.skip_bytes(Link::size);
431+
sink.write_bytes(key);
432+
433+
if constexpr (!is_slab)
434+
{
435+
BC_DEBUG_ONLY(sink.set_limit(Size * element.count());)
409436
}
410437

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

414442
} // namespace database

include/bitcoin/database/impl/primitives/linkage.ipp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,21 +44,36 @@ inline CLASS::linkage(const bytes& other) NOEXCEPT
4444
}
4545

4646
TEMPLATE
47-
constexpr linkage<Size>& CLASS::operator=(integer other) NOEXCEPT
47+
constexpr CLASS& CLASS::operator=(integer other) NOEXCEPT
4848
{
4949
value = other;
5050
return *this;
5151
}
5252

5353
TEMPLATE
54-
inline linkage<Size>& CLASS::operator=(const bytes& other) NOEXCEPT
54+
inline CLASS& CLASS::operator=(const bytes& other) NOEXCEPT
5555
{
5656
value = 0;
5757
system::unsafe_array_cast<uint8_t, Size>(&value) = other;
5858
value = system::native_from_little_end(value);
5959
return *this;
6060
}
6161

62+
TEMPLATE
63+
inline CLASS& CLASS::operator++() NOEXCEPT
64+
{
65+
++value;
66+
return *this;
67+
}
68+
69+
TEMPLATE
70+
inline CLASS CLASS::operator++(int) NOEXCEPT
71+
{
72+
auto self = *this;
73+
++(*this);
74+
return self;
75+
}
76+
6277
////TEMPLATE
6378
////constexpr CLASS::operator bool() const NOEXCEPT
6479
////{

0 commit comments

Comments
 (0)