@@ -20,58 +20,32 @@ namespace codegen {
20
20
namespace util {
21
21
22
22
static const uint32_t kDefaultNumElements = 256 ;
23
+ static const uint32_t kNumBlockElems = 1024 ;
23
24
24
25
static_assert ((kDefaultNumElements & (kDefaultNumElements - 1 )) == 0 ,
25
26
" Default number of elements must be a power of two" );
26
- /* *
27
- * This hash-table uses an open-addressing probing scheme
28
- *
29
- */
30
27
31
- HashTable::HashTable (::peloton::type::AbstractPool &memory, uint64_t key_size,
32
- uint64_t value_size)
33
- : memory_(memory),
34
- entry_size_ (sizeof (Entry) + key_size + value_size),
35
- directory_(nullptr ),
36
- directory_size_(0 ),
37
- directory_mask_(0 ),
38
- block_(nullptr ),
39
- next_tuple_pos_(nullptr ),
40
- available_bytes_(0 ),
41
- num_elems_(0 ),
42
- capacity_(0 ) {
43
- // Upon creation, we allocate room for kDefaultNumElements in the hash table.
44
- // We assume 50% load factor on the directory, thus the directory size is
45
- // twice the number of elements.
46
- directory_size_ = kDefaultNumElements * 2 ;
47
- directory_mask_ = directory_size_ - 1 ;
48
- directory_ = static_cast <Entry **>(
49
- memory_.Allocate (sizeof (Entry *) * directory_size_));
50
- PELOTON_MEMSET (directory_, 0 , directory_size_);
28
+ // //////////////////////////////////////////////////////////////////////////////
29
+ // /
30
+ // / EntryBuffer
31
+ // /
32
+ // //////////////////////////////////////////////////////////////////////////////
51
33
34
+ HashTable::EntryBuffer::EntryBuffer (::peloton::type::AbstractPool &memory,
35
+ uint64_t entry_size)
36
+ : memory_(memory), entry_size_(entry_size) {
52
37
// We also need to allocate some space to store tuples. Tuples are stored
53
38
// externally from the main hash table in a separate values memory space.
54
- uint64_t block_size =
55
- sizeof (MemoryBlock) + (entry_size_ * kDefaultNumElements );
39
+ uint64_t block_size = sizeof (MemoryBlock) + (entry_size_ * kNumBlockElems );
56
40
block_ = reinterpret_cast <MemoryBlock *>(memory_.Allocate (block_size));
57
41
block_->next = nullptr ;
58
42
59
43
// Set the next tuple write position and the available bytes
60
- next_tuple_pos_ = block_->data ;
44
+ next_entry_ = block_->data ;
61
45
available_bytes_ = block_size - sizeof (MemoryBlock);
62
-
63
- // Set table stats
64
- num_elems_ = 0 ;
65
- capacity_ = kDefaultNumElements ;
66
46
}
67
47
68
- HashTable::~HashTable () {
69
- // Free the directory
70
- if (directory_ != nullptr ) {
71
- memory_.Free (directory_);
72
- directory_ = nullptr ;
73
- }
74
-
48
+ HashTable::EntryBuffer::~EntryBuffer () {
75
49
// Free all the blocks we've allocated
76
50
MemoryBlock *block = block_;
77
51
while (block != nullptr ) {
@@ -82,41 +56,77 @@ HashTable::~HashTable() {
82
56
block_ = nullptr ;
83
57
}
84
58
85
- void HashTable::Init (HashTable &table, executor::ExecutorContext &exec_ctx,
86
- uint64_t key_size, uint64_t value_size) {
87
- new (&table) HashTable (*exec_ctx.GetPool (), key_size, value_size);
88
- }
89
-
90
- void HashTable::Destroy (HashTable &table) { table.~HashTable (); }
91
-
92
- HashTable::Entry *HashTable::AcquireEntrySlot () {
59
+ HashTable::Entry *HashTable::EntryBuffer::NextFree () {
93
60
if (entry_size_ > available_bytes_) {
94
- capacity_ *= 2 ;
95
- uint64_t block_size = sizeof (MemoryBlock) + (entry_size_ * capacity_);
61
+ uint64_t block_size = sizeof (MemoryBlock) + (entry_size_ * kNumBlockElems );
96
62
auto *new_block =
97
63
reinterpret_cast <MemoryBlock *>(memory_.Allocate (block_size));
98
64
new_block->next = block_;
99
65
block_ = new_block;
100
- next_tuple_pos_ = new_block->data ;
66
+ next_entry_ = new_block->data ;
101
67
available_bytes_ = block_size - sizeof (MemoryBlock);
102
68
}
103
69
104
- auto *entry = reinterpret_cast <Entry *>(next_tuple_pos_ );
70
+ auto *entry = reinterpret_cast <Entry *>(next_entry_ );
105
71
entry->next = nullptr ;
106
72
107
- next_tuple_pos_ += entry_size_;
73
+ next_entry_ += entry_size_;
108
74
available_bytes_ -= entry_size_;
109
- num_elems_++;
110
75
111
76
return entry;
112
77
}
113
78
79
+ // //////////////////////////////////////////////////////////////////////////////
80
+ // /
81
+ // / Hash Table
82
+ // /
83
+ // //////////////////////////////////////////////////////////////////////////////
84
+
85
+ /* *
86
+ * This hash-table uses an open-addressing probing scheme
87
+ *
88
+ */
89
+
90
+ HashTable::HashTable (::peloton::type::AbstractPool &memory, uint64_t key_size,
91
+ uint64_t value_size)
92
+ : memory_(memory),
93
+ directory_ (nullptr ),
94
+ directory_size_(0 ),
95
+ directory_mask_(0 ),
96
+ entry_buffer_(memory, Entry::Size(key_size, value_size)),
97
+ num_elems_(0 ),
98
+ capacity_(kDefaultNumElements ) {
99
+ // Upon creation, we allocate room for kDefaultNumElements in the hash table.
100
+ // We assume 50% load factor on the directory, thus the directory size is
101
+ // twice the number of elements.
102
+ directory_size_ = capacity_ * 2 ;
103
+ directory_mask_ = directory_size_ - 1 ;
104
+ directory_ = static_cast <Entry **>(
105
+ memory_.Allocate (sizeof (Entry *) * directory_size_));
106
+ PELOTON_MEMSET (directory_, 0 , directory_size_);
107
+ }
108
+
109
+ HashTable::~HashTable () {
110
+ // Free the directory
111
+ if (directory_ != nullptr ) {
112
+ memory_.Free (directory_);
113
+ directory_ = nullptr ;
114
+ }
115
+ }
116
+
117
+ void HashTable::Init (HashTable &table, executor::ExecutorContext &exec_ctx,
118
+ uint64_t key_size, uint64_t value_size) {
119
+ new (&table) HashTable (*exec_ctx.GetPool (), key_size, value_size);
120
+ }
121
+
122
+ void HashTable::Destroy (HashTable &table) { table.~HashTable (); }
123
+
114
124
char *HashTable::StoreTupleLazy (uint64_t hash) {
115
125
// Since this is a lazy insertion, we just need to acquire/allocate an entry
116
126
// from storage. It is assumed that actual construction of the hash table is
117
127
// done by a subsequent call to BuildLazy() only after ALL lazy insertions
118
128
// have completed.
119
- auto *entry = AcquireEntrySlot ();
129
+ auto *entry = entry_buffer_. NextFree ();
120
130
entry->hash = hash;
121
131
122
132
// Insert the entry into the linked list in the first directory slot
@@ -129,6 +139,8 @@ char *HashTable::StoreTupleLazy(uint64_t hash) {
129
139
directory_[1 ] = entry;
130
140
}
131
141
142
+ num_elems_++;
143
+
132
144
// Return data pointer for key/value storage
133
145
return entry->data ;
134
146
}
@@ -140,14 +152,16 @@ char *HashTable::StoreTuple(uint64_t hash) {
140
152
}
141
153
142
154
// Acquire/allocate an entry from storage
143
- Entry *entry = AcquireEntrySlot ();
155
+ Entry *entry = entry_buffer_. NextFree ();
144
156
entry->hash = hash;
145
157
146
158
// Insert into hash table
147
159
uint64_t index = hash & directory_mask_;
148
160
entry->next = directory_[index];
149
161
directory_[index] = entry;
150
162
163
+ num_elems_++;
164
+
151
165
// Return data pointer for key/value storage
152
166
return entry->data ;
153
167
}
0 commit comments