Skip to content

Commit fbf59f5

Browse files
Ravi Nagarjun AkellaRavi Nagarjun Akella
authored andcommitted
use try_lock to delete the evicted entry from hashmap on a best effort basis
1 parent bc40a3b commit fbf59f5

File tree

3 files changed

+46
-33
lines changed

3 files changed

+46
-33
lines changed

include/sisl/cache/simple_cache.hpp

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ class SimpleCache {
3434
uint32_t m_per_value_size;
3535

3636
static thread_local std::set< K > t_failed_keys;
37-
static thread_local std::set< K > t_evicted_keys;
3837

3938
public:
4039
SimpleCache(const std::shared_ptr< Evictor >& evictor, uint32_t num_buckets, uint32_t per_val_size,
@@ -46,7 +45,7 @@ class SimpleCache {
4645
m_record_family_id = m_evictor->register_record_family(std::move(evict_cb), [this](const CacheRecord& record) {
4746
V const value = reinterpret_cast<SingleEntryHashNode< V >*>(const_cast< CacheRecord* >(&record))->m_value;
4847
K key = m_key_extract_cb(value);
49-
t_evicted_keys.insert(key);
48+
return m_map.try_erase(key);
5049
});
5150
}
5251

@@ -55,14 +54,6 @@ class SimpleCache {
5554
bool insert(const V& value) {
5655
K k = m_key_extract_cb(value);
5756
bool ret = m_map.insert(k, value);
58-
// erase evicted keys
59-
if (t_evicted_keys.size() > 0) {
60-
for (const auto& key : t_evicted_keys) {
61-
V out_val;
62-
m_map.erase(key, out_val);
63-
}
64-
t_evicted_keys.clear();
65-
}
6657
return ret;
6758
}
6859

@@ -116,6 +107,4 @@ class SimpleCache {
116107
template < typename K, typename V >
117108
thread_local std::set< K > SimpleCache< K, V >::t_failed_keys;
118109

119-
template < typename K, typename V >
120-
thread_local std::set< K > SimpleCache< K, V >::t_evicted_keys;
121110
} // namespace sisl

include/sisl/cache/simple_hashmap.hpp

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ class SimpleHashMap {
7373
bool upsert(const K& key, const V& value);
7474
bool get(const K& input_key, V& out_val);
7575
bool erase(const K& key, V& out_val);
76+
bool try_erase(const K& key);
7677
bool update(const K& key, auto&& update_cb);
7778
bool upsert_or_delete(const K& key, auto&& update_or_delete_cb);
7879

@@ -184,27 +185,21 @@ class SimpleHashBucket {
184185
#ifndef GLOBAL_HASHSET_LOCK
185186
folly::SharedMutexWritePriority::WriteHolder holder(m_lock);
186187
#endif
187-
SingleEntryHashNode< V >* n = nullptr;
188-
189-
auto it = m_list.begin();
190-
for (auto itend{m_list.end()}; it != itend; ++it) {
191-
const K k = SimpleHashMap< K, V >::extractor_cb()(it->m_value);
192-
if (input_key > k) {
193-
break;
194-
} else if (input_key == k) {
195-
n = &*it;
196-
break;
197-
}
198-
}
188+
return erase_unsafe(input_key, out_val, true /* call_access_cb */);
189+
}
199190

200-
if (n) {
201-
access_cb(*n, input_key, hash_op_t::DELETE);
202-
out_val = n->m_value;
203-
m_list.erase(it);
204-
delete n;
205-
return true;
191+
bool try_erase(const K& input_key) {
192+
V dummy_val;
193+
#ifndef GLOBAL_HASHSET_LOCK
194+
if(m_lock.try_lock()) {
195+
bool ret = erase_unsafe(input_key, dummy_val, false /* call_access_cb */);
196+
m_lock.unlock();
197+
return ret;
198+
} else {
199+
return false;
206200
}
207-
return false;
201+
#endif
202+
return erase_unsafe(input_key, dummy_val, false);
208203
}
209204

210205
bool upsert_or_delete(const K& input_key, auto&& update_or_delete_cb) {
@@ -266,9 +261,33 @@ class SimpleHashBucket {
266261
static void access_cb(const SingleEntryHashNode< V >& node, const K& key, hash_op_t op) {
267262
SimpleHashMap< K, V >::call_access_cb((const ValueEntryBase&)node, key, op);
268263
}
264+
265+
bool erase_unsafe(const K& input_key, V& out_val, bool call_access_cb) {
266+
SingleEntryHashNode< V >* n = nullptr;
267+
268+
auto it = m_list.begin();
269+
for (auto itend{m_list.end()}; it != itend; ++it) {
270+
const K k = SimpleHashMap< K, V >::extractor_cb()(it->m_value);
271+
if (input_key > k) {
272+
break;
273+
} else if (input_key == k) {
274+
n = &*it;
275+
break;
276+
}
277+
}
278+
279+
if (n) {
280+
if (call_access_cb) { access_cb(*n, input_key, hash_op_t::DELETE); }
281+
out_val = n->m_value;
282+
m_list.erase(it);
283+
delete n;
284+
return true;
285+
}
286+
return false;
287+
}
269288
};
270289

271-
///////////////////////////////////////////// RangeHashMap Definitions ///////////////////////////////////
290+
///////////////////////////////////////////// SimpleHashMap Definitions ///////////////////////////////////
272291
template < typename K, typename V >
273292
SimpleHashMap< K, V >::SimpleHashMap(uint32_t nBuckets, const key_extractor_cb_t< K, V >& extract_cb,
274293
key_access_cb_t< K > access_cb) :
@@ -317,6 +336,12 @@ bool SimpleHashMap< K, V >::erase(const K& key, V& out_val) {
317336
return get_bucket(key).erase(key, out_val);
318337
}
319338

339+
template < typename K, typename V >
340+
bool SimpleHashMap< K, V >::try_erase(const K& key) {
341+
set_current_instance(this);
342+
return get_bucket(key).try_erase(key);
343+
}
344+
320345
/// This is a special atomic operation where user can insert_or_update_or_erase based on condition atomically. It
321346
/// performs differently based on certain conditions.
322347
///

src/cache/tests/test_simple_cache.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,6 @@ TEST(SimpleCacheSize, TriggerEvict) {
231231
++cache_hits;
232232
}
233233
}
234-
ASSERT_EQ(cache_hits, num_partitions * max_nodes_per_partition);
235234
}
236235

237236
TEST(SimpleCacheSize, MultithreadedEviction) {

0 commit comments

Comments
 (0)