Skip to content

Commit ed2af50

Browse files
committed
critical section inside combined_lock
1 parent 0f2fe81 commit ed2af50

File tree

7 files changed

+71
-28
lines changed

7 files changed

+71
-28
lines changed

cachelib/allocator/CacheAllocator-inl.h

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1452,26 +1452,39 @@ CacheAllocator<CacheTrait>::findEviction(TierId tid, PoolId pid, ClassId cid) {
14521452
// Keep searching for a candidate until we were able to evict it
14531453
// or until the search limit has been exhausted
14541454
unsigned int searchTries = 0;
1455-
auto itr = mmContainer.getEvictionIterator();
14561455
while ((config_.evictionSearchTries == 0 ||
1457-
config_.evictionSearchTries > searchTries) &&
1458-
itr) {
1456+
config_.evictionSearchTries > searchTries)) {
14591457
++searchTries;
14601458

1461-
Item* toRecycle = itr.get();
1459+
Item* toRecycle = nullptr;
1460+
Item* candidate = nullptr;
14621461

1463-
Item* candidate =
1464-
toRecycle->isChainedItem()
1465-
? &toRecycle->asChainedItem().getParentItem(compressor_)
1466-
: toRecycle;
1462+
mmContainer.withEvictionIterator([this, &candidate, &toRecycle, &searchTries](auto &&itr){
1463+
while ((config_.evictionSearchTries == 0 ||
1464+
config_.evictionSearchTries > searchTries) && itr) {
1465+
++searchTries;
14671466

1468-
// make sure no other thead is evicting the item
1469-
if (candidate->getRefCount() != 0 || !candidate->markMoving()) {
1470-
++itr;
1467+
auto *toRecycle_ = itr.get();
1468+
auto *candidate_ = toRecycle_->isChainedItem()
1469+
? &toRecycle_->asChainedItem().getParentItem(compressor_)
1470+
: toRecycle_;
1471+
1472+
// make sure no other thead is evicting the item
1473+
if (candidate_->getRefCount() == 0 && candidate_->markMoving()) {
1474+
toRecycle = toRecycle_;
1475+
candidate = candidate_;
1476+
return;
1477+
}
1478+
1479+
++itr;
1480+
}
1481+
});
1482+
1483+
if (!toRecycle)
14711484
continue;
1472-
}
1473-
1474-
itr.destroy();
1485+
1486+
XDCHECK(toRecycle);
1487+
XDCHECK(candidate);
14751488

14761489
// for chained items, the ownership of the parent can change. We try to
14771490
// evict what we think as parent and see if the eviction of parent
@@ -1525,8 +1538,6 @@ CacheAllocator<CacheTrait>::findEviction(TierId tid, PoolId pid, ClassId cid) {
15251538
return toRecycle;
15261539
}
15271540
}
1528-
1529-
itr.resetToBegin();
15301541
}
15311542
return nullptr;
15321543
}

cachelib/allocator/MM2Q-inl.h

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -238,22 +238,21 @@ MM2Q::Container<T, HookPtr>::getEvictionIterator() const noexcept {
238238
// arbitrary amount of time outside a lambda-friendly piece of code (eg. they
239239
// can return the iterator from functions, pass it to functions, etc)
240240
//
241-
// it would be theoretically possible to refactor this interface into
242-
// something like the following to allow combining
243-
//
244-
// mm2q.withEvictionIterator([&](auto iterator) {
245-
// // user code
246-
// });
247-
//
248-
// at the time of writing it is unclear if the gains from combining are
249-
// reasonable justification for the codemod required to achieve combinability
250-
// as we don't expect this critical section to be the hotspot in user code.
251-
// This is however subject to change at some time in the future as and when
252-
// this assertion becomes false.
241+
// to get advantage of combining, use withEvictionIterator
253242
LockHolder l(*lruMutex_);
254243
return Iterator{std::move(l), lru_.rbegin()};
255244
}
256245

246+
template <typename T, MM2Q::Hook<T> T::*HookPtr>
247+
template <typename F>
248+
void
249+
MM2Q::Container<T, HookPtr>::withEvictionIterator(F&& fun) {
250+
lruMutex_->lock_combine([this, &fun]() {
251+
fun(Iterator{LockHolder{}, lru_.rbegin()});
252+
});
253+
}
254+
255+
257256
template <typename T, MM2Q::Hook<T> T::*HookPtr>
258257
void MM2Q::Container<T, HookPtr>::removeLocked(T& node,
259258
bool doRebalance) noexcept {

cachelib/allocator/MM2Q.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,11 @@ class MM2Q {
438438
// container and only one such iterator can exist at a time
439439
Iterator getEvictionIterator() const noexcept;
440440

441+
// Execute provided function under container lock. Function gets
442+
// iterator passed as parameter.
443+
template <typename F>
444+
void withEvictionIterator(F&& f);
445+
441446
// get the current config as a copy
442447
Config getConfig() const;
443448

cachelib/allocator/MMLru-inl.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,15 @@ MMLru::Container<T, HookPtr>::getEvictionIterator() const noexcept {
225225
return Iterator{std::move(l), lru_.rbegin()};
226226
}
227227

228+
template <typename T, MMLru::Hook<T> T::*HookPtr>
229+
template <typename F>
230+
void
231+
MMLru::Container<T, HookPtr>::withEvictionIterator(F&& fun) {
232+
lruMutex_->lock_combine([this, &fun]() {
233+
fun(Iterator{LockHolder{}, lru_.rbegin()});
234+
});
235+
}
236+
228237
template <typename T, MMLru::Hook<T> T::*HookPtr>
229238
void MMLru::Container<T, HookPtr>::ensureNotInsertionPoint(T& node) noexcept {
230239
// If we are removing the insertion point node, grow tail before we remove

cachelib/allocator/MMLru.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,11 @@ class MMLru {
333333
// container and only one such iterator can exist at a time
334334
Iterator getEvictionIterator() const noexcept;
335335

336+
// Execute provided function under container lock. Function gets
337+
// iterator passed as parameter.
338+
template <typename F>
339+
void withEvictionIterator(F&& f);
340+
336341
// get copy of current config
337342
Config getConfig() const;
338343

cachelib/allocator/MMTinyLFU-inl.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,15 @@ MMTinyLFU::Container<T, HookPtr>::getEvictionIterator() const noexcept {
220220
return Iterator{std::move(l), *this};
221221
}
222222

223+
template <typename T, MMTinyLFU::Hook<T> T::*HookPtr>
224+
template <typename F>
225+
void
226+
MMTinyLFU::Container<T, HookPtr>::withEvictionIterator(F&& fun) {
227+
LockHolder l(lruMutex_);
228+
fun(Iterator{LockHolder{}, *this});
229+
}
230+
231+
223232
template <typename T, MMTinyLFU::Hook<T> T::*HookPtr>
224233
void MMTinyLFU::Container<T, HookPtr>::removeLocked(T& node) noexcept {
225234
if (isTiny(node)) {

cachelib/allocator/MMTinyLFU.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,11 @@ class MMTinyLFU {
491491
// container and only one such iterator can exist at a time
492492
Iterator getEvictionIterator() const noexcept;
493493

494+
// Execute provided function under container lock. Function gets
495+
// iterator passed as parameter.
496+
template <typename F>
497+
void withEvictionIterator(F&& f);
498+
494499
// for saving the state of the lru
495500
//
496501
// precondition: serialization must happen without any reader or writer

0 commit comments

Comments
 (0)