Skip to content
This repository was archived by the owner on Mar 22, 2023. It is now read-only.

Commit 8a89047

Browse files
Merge pull request #936 from JanDorniak99/concurrent_defrag_test
add concurrent_hash_map concurrent erase defrag test
2 parents a66c005 + 889f819 commit 8a89047

1 file changed

Lines changed: 93 additions & 1 deletion

File tree

tests/concurrent_hash_map_defrag/concurrent_hash_map_defrag.cpp

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ class string_hasher {
4949
return hash(str.c_str(), str.size());
5050
}
5151

52+
size_t
53+
operator()(const std::string &str) const
54+
{
55+
return hash(str.c_str(), str.size());
56+
}
57+
5258
private:
5359
size_t
5460
hash(const char *str, size_t size) const
@@ -70,7 +76,7 @@ struct root {
7076
};
7177

7278
/*
73-
* insert_and_erase_test_str -- (internal) test insert and erase operations
79+
* insert_defrag_lookup -- test insert, erase and defrag operations
7480
* pmem::obj::concurrent_hash_map<pmem::obj::string, pmem::obj::string>
7581
*/
7682
void
@@ -159,6 +165,88 @@ insert_defrag_lookup_test(nvobj::pool<root> &pop)
159165
persistent_map_type::value_type>(ptr[i]);
160166
}
161167
});
168+
169+
map->clear();
170+
}
171+
172+
/*
173+
* insert_defrag_concurrent -- test concurrently erase and defrag operations
174+
* pmem::obj::concurrent_hash_map<pmem::obj::string, pmem::obj::string>
175+
*/
176+
void
177+
erase_defrag_concurrent_test(nvobj::pool<root> &pop, bool reversed_order,
178+
size_t erase_threads_n)
179+
{
180+
const ptrdiff_t BATCH_SIZE = 1000;
181+
const size_t NUMBER_ITEMS_ERASE = BATCH_SIZE * erase_threads_n;
182+
const size_t NUMBER_ITEMS_SAVE = 100;
183+
184+
auto map = pop.root()->cons;
185+
186+
UT_ASSERT(map != nullptr);
187+
188+
map->runtime_initialize();
189+
190+
std::string str = " ";
191+
for (size_t i = 0; i < NUMBER_ITEMS_ERASE + NUMBER_ITEMS_SAVE; i++) {
192+
map->insert_or_assign(str, str);
193+
str.append(std::to_string(i));
194+
}
195+
196+
std::vector<std::string> elements_to_erase;
197+
std::vector<std::string> elements_to_save;
198+
199+
size_t cnt = 0;
200+
for (auto &v : *map) {
201+
/* first NUMBER_ITEMS_SAVE elements wont be erased */
202+
if (cnt++ < NUMBER_ITEMS_SAVE)
203+
elements_to_save.push_back(
204+
std::string(v.first.c_str()));
205+
else
206+
elements_to_erase.push_back(
207+
std::string(v.first.c_str()));
208+
}
209+
210+
/* reverse order of elements_to_erase to test case when we are erasing
211+
* in order from last element to first */
212+
if (reversed_order)
213+
std::reverse(elements_to_erase.begin(),
214+
elements_to_erase.end());
215+
216+
std::vector<std::thread> threads;
217+
for (ptrdiff_t i = 0; i < static_cast<ptrdiff_t>(erase_threads_n);
218+
i++) {
219+
threads.emplace_back([&, i]() {
220+
auto start = std::next(elements_to_erase.begin(),
221+
i * BATCH_SIZE);
222+
auto end = std::next(elements_to_erase.begin(),
223+
(i + 1) * BATCH_SIZE);
224+
for (auto it = start; it != end; ++it) {
225+
UT_ASSERT(map->erase(*it));
226+
}
227+
});
228+
}
229+
230+
threads.emplace_back([&]() { map->defragment(); });
231+
232+
for (auto &thread : threads)
233+
thread.join();
234+
235+
UT_ASSERT(map->size() == NUMBER_ITEMS_SAVE);
236+
237+
for (size_t i = 0; i < NUMBER_ITEMS_SAVE; ++i) {
238+
persistent_map_type::accessor acc;
239+
bool res = map->find(acc, elements_to_save[i]);
240+
241+
if (res) {
242+
UT_ASSERT(acc->first == (elements_to_save[i]));
243+
UT_ASSERT(acc->second == (elements_to_save[i]));
244+
} else {
245+
UT_ASSERT(false);
246+
}
247+
}
248+
249+
map->clear();
162250
}
163251
}
164252

@@ -185,6 +273,10 @@ test(int argc, char *argv[])
185273
}
186274

187275
insert_defrag_lookup_test(pop);
276+
erase_defrag_concurrent_test(pop, false, 1);
277+
erase_defrag_concurrent_test(pop, true, 1);
278+
erase_defrag_concurrent_test(pop, false, 10);
279+
erase_defrag_concurrent_test(pop, true, 10);
188280

189281
pop.close();
190282
}

0 commit comments

Comments
 (0)