Skip to content

Commit 52d3e84

Browse files
committed
Change hashmaps to base2 buckets.
1 parent d62bb47 commit 52d3e84

20 files changed

Lines changed: 288 additions & 221 deletions

File tree

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ namespace database {
2828

2929
TEMPLATE
3030
CLASS::arrayhead(storage& head, const Link& buckets) NOEXCEPT
31-
: file_(head), initial_buckets_(buckets)
31+
: file_(head), initial_buckets_(buckets.value)
3232
{
3333
}
3434

@@ -49,7 +49,7 @@ inline size_t CLASS::buckets() const NOEXCEPT
4949
TEMPLATE
5050
bool CLASS::enabled() const NOEXCEPT
5151
{
52-
return initial_buckets_ > one;
52+
return !is_zero(initial_buckets_);
5353
}
5454

5555
TEMPLATE

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

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@ namespace libbitcoin {
3030
namespace database {
3131

3232
TEMPLATE
33-
CLASS::hashhead(storage& head, const Link& buckets) NOEXCEPT
34-
: file_(head), buckets_(buckets)
33+
CLASS::hashhead(storage& head, size_t bits) NOEXCEPT
34+
: file_(head),
35+
buckets_(system::power2<Link::integer>(bits)),
36+
mask_(system::unmask_right<Link::integer>(bits))
3537
{
3638
}
3739

@@ -103,13 +105,13 @@ bool CLASS::set_body_count(const Link& count) NOEXCEPT
103105
TEMPLATE
104106
inline Link CLASS::index(const Key& key) const NOEXCEPT
105107
{
108+
using namespace system;
109+
BC_ASSERT_MSG(mask_ < max_size_t, "insufficient domain");
106110
BC_ASSERT_MSG(is_nonzero(buckets_), "hash table requires buckets");
107111

108112
// unique_hash assumes sufficient uniqueness in low order key bytes.
109-
return system::unique_hash(key) % buckets_;
110-
111-
// TODO: restrict buckets to power of two and replace modulo above with
112-
// return and(sub1(buckets), unique_hash(key)) [and() is much faster].
113+
const auto index = possible_narrow_cast<Link::integer>(unique_hash(key));
114+
return bit_and<Link::integer>(mask_, index);
113115
}
114116

115117
TEMPLATE

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ bool CLASS::commit(const Link& link, const Key& key) NOEXCEPT
334334
unsafe_array_cast<uint8_t, key_size>(std::next(ptr->begin(),
335335
Link::size)) = key;
336336

337-
// Commit element to search index.
337+
// Commit element to search index (terminal is a valid bucket index).
338338
auto& next = unsafe_array_cast<uint8_t, Link::size>(ptr->begin());
339339
return head_.push(link, next, head_.index(key));
340340
}
@@ -438,6 +438,7 @@ bool CLASS::write(const memory_ptr& ptr, const Link& link, const Key& key,
438438
sink.skip_bytes(Link::size);
439439
sink.write_bytes(key);
440440

441+
// Commit element to body and search (terminal is a valid bucket index).
441442
if constexpr (!is_slab) { BC_DEBUG_ONLY(sink.set_limit(Size * element.count());) }
442443
auto& next = unsafe_array_cast<uint8_t, Link::size>(offset);
443444
return element.to_data(sink) && head_.push(link, next, head_.index(key));

include/bitcoin/database/impl/store.ipp

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@
1919
#ifndef LIBBITCOIN_DATABASE_STORE_IPP
2020
#define LIBBITCOIN_DATABASE_STORE_IPP
2121

22-
#include <algorithm>
23-
#include <chrono>
22+
#include <unordered_map>
2423
#include <bitcoin/system.hpp>
2524
#include <bitcoin/database/boost.hpp>
2625
#include <bitcoin/database/define.hpp>
@@ -33,10 +32,6 @@ namespace database {
3332

3433
BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
3534

36-
// head doesn't guard (performance) and parameter is cast to Link object,
37-
// so establish 1 as the minimum value (which also implies disabled).
38-
constexpr auto nonzero = 1_u32;
39-
4035
// public
4136
// ----------------------------------------------------------------------------
4237

@@ -136,7 +131,7 @@ CLASS::store(const settings& config) NOEXCEPT
136131

137132
header_head_(head(config.path / schema::dir::heads, schema::archive::header)),
138133
header_body_(body(config.path, schema::archive::header), config.header_size, config.header_rate),
139-
header(header_head_, header_body_, std::max(config.header_buckets, nonzero)),
134+
header(header_head_, header_body_, config.header_bits),
140135

141136
input_head_(head(config.path / schema::dir::heads, schema::archive::input)),
142137
input_body_(body(config.path, schema::archive::input), config.input_size, config.input_rate),
@@ -148,7 +143,7 @@ CLASS::store(const settings& config) NOEXCEPT
148143

149144
point_head_(head(config.path / schema::dir::heads, schema::archive::point)),
150145
point_body_(body(config.path, schema::archive::point), config.point_size, config.point_rate),
151-
point(point_head_, point_body_, std::max(config.point_buckets, nonzero)),
146+
point(point_head_, point_body_, config.point_bits),
152147

153148
ins_head_(head(config.path / schema::dir::heads, schema::archive::ins)),
154149
ins_body_(body(config.path, schema::archive::ins), config.ins_size, config.ins_rate),
@@ -160,11 +155,11 @@ CLASS::store(const settings& config) NOEXCEPT
160155

161156
tx_head_(head(config.path / schema::dir::heads, schema::archive::tx)),
162157
tx_body_(body(config.path, schema::archive::tx), config.tx_size, config.tx_rate),
163-
tx(tx_head_, tx_body_, std::max(config.tx_buckets, nonzero)),
158+
tx(tx_head_, tx_body_, config.tx_bits),
164159

165160
txs_head_(head(config.path / schema::dir::heads, schema::archive::txs)),
166161
txs_body_(body(config.path, schema::archive::txs), config.txs_size, config.txs_rate),
167-
txs(txs_head_, txs_body_, std::max(config.txs_buckets, nonzero)),
162+
txs(txs_head_, txs_body_, config.txs_bits),
168163

169164
// Indexes.
170165
// ------------------------------------------------------------------------
@@ -179,37 +174,33 @@ CLASS::store(const settings& config) NOEXCEPT
179174

180175
strong_tx_head_(head(config.path / schema::dir::heads, schema::indexes::strong_tx)),
181176
strong_tx_body_(body(config.path, schema::indexes::strong_tx), config.strong_tx_size, config.strong_tx_rate),
182-
strong_tx(strong_tx_head_, strong_tx_body_, std::max(config.strong_tx_buckets, nonzero)),
177+
strong_tx(strong_tx_head_, strong_tx_body_, config.strong_tx_bits),
183178

184179
// Caches.
185180
// ------------------------------------------------------------------------
186181

187182
prevout_head_(head(config.path / schema::dir::heads, schema::caches::prevout)),
188183
prevout_body_(body(config.path, schema::caches::prevout), config.prevout_size, config.prevout_rate),
189-
prevout(prevout_head_, prevout_body_, std::max(config.prevout_buckets, nonzero)),
184+
prevout(prevout_head_, prevout_body_, config.prevout_buckets),
190185

191186
validated_bk_head_(head(config.path / schema::dir::heads, schema::caches::validated_bk)),
192187
validated_bk_body_(body(config.path, schema::caches::validated_bk), config.validated_bk_size, config.validated_bk_rate),
193-
validated_bk(validated_bk_head_, validated_bk_body_, std::max(config.validated_bk_buckets, nonzero)),
188+
validated_bk(validated_bk_head_, validated_bk_body_, config.validated_bk_bits),
194189

195190
validated_tx_head_(head(config.path / schema::dir::heads, schema::caches::validated_tx)),
196191
validated_tx_body_(body(config.path, schema::caches::validated_tx), config.validated_tx_size, config.validated_tx_rate),
197-
validated_tx(validated_tx_head_, validated_tx_body_, std::max(config.validated_tx_buckets, nonzero)),
192+
validated_tx(validated_tx_head_, validated_tx_body_, config.validated_tx_bits),
198193

199194
// Optionals.
200195
// ------------------------------------------------------------------------
201196

202197
address_head_(head(config.path / schema::dir::heads, schema::optionals::address)),
203198
address_body_(body(config.path, schema::optionals::address), config.address_size, config.address_rate),
204-
address(address_head_, address_body_, std::max(config.address_buckets, nonzero)),
199+
address(address_head_, address_body_, config.address_bits),
205200

206201
neutrino_head_(head(config.path / schema::dir::heads, schema::optionals::neutrino)),
207202
neutrino_body_(body(config.path, schema::optionals::neutrino), config.neutrino_size, config.neutrino_rate),
208-
neutrino(neutrino_head_, neutrino_body_, std::max(config.neutrino_buckets, nonzero)),
209-
210-
////bootstrap_head_(head(config.path / schema::dir::heads, schema::optionals::bootstrap)),
211-
////bootstrap_body_(body(config.path, schema::optionals::bootstrap), config.bootstrap_size, config.bootstrap_rate),
212-
////bootstrap(bootstrap_head_, bootstrap_body_),
203+
neutrino(neutrino_head_, neutrino_body_, config.neutrino_bits),
213204

214205
// Locks.
215206
// ------------------------------------------------------------------------

include/bitcoin/database/primitives/hashhead.hpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ class hashhead
3535

3636
using bytes = typename Link::bytes;
3737

38-
/// A hash head has zero buckets (and cannot call index()).
39-
hashhead(storage& head, const Link& buckets) NOEXCEPT;
38+
/// An hash head is disabled it if has one or less buckets (0 bits).
39+
hashhead(storage& head, size_t bits) NOEXCEPT;
4040

4141
/// Sizing (thread safe).
4242
inline size_t size() const NOEXCEPT;
@@ -52,7 +52,8 @@ class hashhead
5252
bool get_body_count(Link& count) const NOEXCEPT;
5353
bool set_body_count(const Link& count) NOEXCEPT;
5454

55-
/// Convert natural key to head bucket index.
55+
/// Convert natural key to head bucket index (all keys are valid).
56+
/// Terminal is a valid bucket index (just not a valid bucket value).
5657
inline Link index(const Key& key) const NOEXCEPT;
5758

5859
/// Unsafe if verify false.
@@ -80,6 +81,7 @@ class hashhead
8081

8182
storage& file_;
8283
const Link buckets_;
84+
const Link mask_;
8385
mutable std::shared_mutex mutex_{};
8486
};
8587

include/bitcoin/database/settings.hpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ struct BCD_API settings
4242
/// Archives.
4343
/// -----------------------------------------------------------------------
4444

45-
uint32_t header_buckets;
45+
uint32_t header_bits;
4646
uint64_t header_size;
4747
uint16_t header_rate;
4848

@@ -52,7 +52,7 @@ struct BCD_API settings
5252
uint64_t output_size;
5353
uint16_t output_rate;
5454

55-
uint32_t point_buckets;
55+
uint32_t point_bits;
5656
uint64_t point_size;
5757
uint16_t point_rate;
5858

@@ -62,11 +62,11 @@ struct BCD_API settings
6262
uint64_t puts_size;
6363
uint16_t puts_rate;
6464

65-
uint32_t tx_buckets;
65+
uint32_t tx_bits;
6666
uint64_t tx_size;
6767
uint16_t tx_rate;
6868

69-
uint32_t txs_buckets;
69+
uint32_t txs_bits;
7070
uint64_t txs_size;
7171
uint16_t txs_rate;
7272

@@ -79,7 +79,7 @@ struct BCD_API settings
7979
uint64_t confirmed_size;
8080
uint16_t confirmed_rate;
8181

82-
uint32_t strong_tx_buckets;
82+
uint32_t strong_tx_bits;
8383
uint64_t strong_tx_size;
8484
uint16_t strong_tx_rate;
8585

@@ -90,22 +90,22 @@ struct BCD_API settings
9090
uint64_t prevout_size;
9191
uint16_t prevout_rate;
9292

93-
uint32_t validated_bk_buckets;
93+
uint32_t validated_bk_bits;
9494
uint64_t validated_bk_size;
9595
uint16_t validated_bk_rate;
9696

97-
uint32_t validated_tx_buckets;
97+
uint32_t validated_tx_bits;
9898
uint64_t validated_tx_size;
9999
uint16_t validated_tx_rate;
100100

101101
/// Optionals.
102102
/// -----------------------------------------------------------------------
103103

104-
uint32_t address_buckets;
104+
uint32_t address_bits;
105105
uint64_t address_size;
106106
uint16_t address_rate;
107107

108-
uint32_t neutrino_buckets;
108+
uint32_t neutrino_bits;
109109
uint64_t neutrino_size;
110110
uint16_t neutrino_rate;
111111

src/settings.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ settings::settings() NOEXCEPT
3131

3232
// Archives.
3333

34-
header_buckets{ 100 },
34+
header_bits{ 7 },
3535
header_size{ 1 },
3636
header_rate{ 50 },
3737

@@ -41,7 +41,7 @@ settings::settings() NOEXCEPT
4141
output_size{ 1 },
4242
output_rate{ 50 },
4343

44-
point_buckets{ 100 },
44+
point_bits{ 7 },
4545
point_size{ 1 },
4646
point_rate{ 50 },
4747

@@ -51,11 +51,11 @@ settings::settings() NOEXCEPT
5151
puts_size{ 1 },
5252
puts_rate{ 50 },
5353

54-
tx_buckets{ 100 },
54+
tx_bits{ 7 },
5555
tx_size{ 1 },
5656
tx_rate{ 50 },
5757

58-
txs_buckets{ 100 },
58+
txs_bits{ 7 },
5959
txs_size{ 1 },
6060
txs_rate{ 50 },
6161

@@ -67,7 +67,7 @@ settings::settings() NOEXCEPT
6767
confirmed_size{ 1 },
6868
confirmed_rate{ 50 },
6969

70-
strong_tx_buckets{ 100 },
70+
strong_tx_bits{ 7 },
7171
strong_tx_size{ 1 },
7272
strong_tx_rate{ 50 },
7373

@@ -77,21 +77,21 @@ settings::settings() NOEXCEPT
7777
prevout_size{ 1 },
7878
prevout_rate{ 50 },
7979

80-
validated_bk_buckets{ 100 },
80+
validated_bk_bits{ 7 },
8181
validated_bk_size{ 1 },
8282
validated_bk_rate{ 50 },
8383

84-
validated_tx_buckets{ 100 },
84+
validated_tx_bits{ 7 },
8585
validated_tx_size{ 1 },
8686
validated_tx_rate{ 50 },
8787

8888
// Optionals.
8989

90-
address_buckets{ 100 },
90+
address_bits{ 7 },
9191
address_size{ 1 },
9292
address_rate{ 50 },
9393

94-
neutrino_buckets{ 100 },
94+
neutrino_bits{ 7 },
9595
neutrino_size{ 1 },
9696
neutrino_rate{ 50 }
9797

test/primitives/arraymap.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,12 @@ BOOST_AUTO_TEST_CASE(arraymap___enabled__non_empty_slab_zero_buckets__false)
105105
BOOST_REQUIRE(!instance.get_fault());
106106
}
107107

108-
BOOST_AUTO_TEST_CASE(arraymap___enabled__empty_slab_one_bucket__false)
108+
BOOST_AUTO_TEST_CASE(arraymap___enabled__empty_slab_one_bucket__true)
109109
{
110110
test::chunk_storage head_store{};
111111
test::chunk_storage body_store{};
112112
slab_table instance{ head_store, body_store, 1 };
113-
BOOST_REQUIRE(!instance.enabled());
113+
BOOST_REQUIRE(instance.enabled());
114114
BOOST_REQUIRE(!instance.get_fault());
115115
}
116116

0 commit comments

Comments
 (0)