Skip to content

Commit f859beb

Browse files
committed
Shorten critical section in findEviction
Remove the item from mmContainer and drop the lock before attempting eviction.
1 parent 2f68e28 commit f859beb

File tree

2 files changed

+20
-53
lines changed

2 files changed

+20
-53
lines changed

cachelib/allocator/CacheAllocator-inl.h

Lines changed: 14 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,13 +1221,15 @@ CacheAllocator<CacheTrait>::findEviction(PoolId pid, ClassId cid) {
12211221
++searchTries;
12221222

12231223
Item* candidate = itr.get();
1224+
mmContainer.remove(itr);
1225+
itr.destroy();
1226+
12241227
// for chained items, the ownership of the parent can change. We try to
12251228
// evict what we think as parent and see if the eviction of parent
12261229
// recycles the child we intend to.
1227-
auto toReleaseHandle =
1228-
itr->isChainedItem()
1229-
? advanceIteratorAndTryEvictChainedItem(itr)
1230-
: advanceIteratorAndTryEvictRegularItem(mmContainer, itr);
1230+
auto toReleaseHandle = candidate->isChainedItem()
1231+
? tryEvictChainedItem(*candidate)
1232+
: tryEvictRegularItem(mmContainer, *candidate);
12311233

12321234
if (toReleaseHandle) {
12331235
if (toReleaseHandle->hasChainedItem()) {
@@ -1236,10 +1238,6 @@ CacheAllocator<CacheTrait>::findEviction(PoolId pid, ClassId cid) {
12361238
(*stats_.regularItemEvictions)[pid][cid].inc();
12371239
}
12381240

1239-
// Invalidate iterator since later on we may use this mmContainer
1240-
// again, which cannot be done unless we drop this iterator
1241-
itr.destroy();
1242-
12431241
// we must be the last handle and for chained items, this will be
12441242
// the parent.
12451243
XDCHECK(toReleaseHandle.get() == candidate || candidate->isChainedItem());
@@ -1263,11 +1261,9 @@ CacheAllocator<CacheTrait>::findEviction(PoolId pid, ClassId cid) {
12631261
}
12641262
}
12651263

1266-
// If we destroyed the itr to possibly evict and failed, we restart
1267-
// from the beginning again
1268-
if (!itr) {
1269-
itr.resetToBegin();
1270-
}
1264+
// Insert item back to the mmContainer if eviction failed.
1265+
mmContainer.add(*candidate);
1266+
itr.resetToBegin();
12711267
}
12721268
return nullptr;
12731269
}
@@ -1322,19 +1318,17 @@ bool CacheAllocator<CacheTrait>::shouldWriteToNvmCacheExclusive(
13221318

13231319
template <typename CacheTrait>
13241320
typename CacheAllocator<CacheTrait>::WriteHandle
1325-
CacheAllocator<CacheTrait>::advanceIteratorAndTryEvictRegularItem(
1326-
MMContainer& mmContainer, EvictionIterator& itr) {
1321+
CacheAllocator<CacheTrait>::tryEvictRegularItem(MMContainer& mmContainer,
1322+
Item& item) {
13271323
// we should flush this to nvmcache if it is not already present in nvmcache
13281324
// and the item is not expired.
1329-
Item& item = *itr;
13301325
const bool evictToNvmCache = shouldWriteToNvmCache(item);
13311326

13321327
auto token = evictToNvmCache ? nvmCache_->createPutToken(item.getKey())
13331328
: typename NvmCacheT::PutToken{};
13341329
// record the in-flight eviciton. If not, we move on to next item to avoid
13351330
// stalling eviction.
13361331
if (evictToNvmCache && !token.isValid()) {
1337-
++itr;
13381332
stats_.evictFailConcurrentFill.inc();
13391333
return WriteHandle{};
13401334
}
@@ -1346,12 +1340,10 @@ CacheAllocator<CacheTrait>::advanceIteratorAndTryEvictRegularItem(
13461340
auto evictHandle = accessContainer_->removeIf(item, &itemEvictionPredicate);
13471341

13481342
if (!evictHandle) {
1349-
++itr;
13501343
stats_.evictFailAC.inc();
13511344
return evictHandle;
13521345
}
13531346

1354-
mmContainer.remove(itr);
13551347
XDCHECK_EQ(reinterpret_cast<uintptr_t>(evictHandle.get()),
13561348
reinterpret_cast<uintptr_t>(&item));
13571349
XDCHECK(!evictHandle->isInMMContainer());
@@ -1366,15 +1358,6 @@ CacheAllocator<CacheTrait>::advanceIteratorAndTryEvictRegularItem(
13661358
return WriteHandle{};
13671359
}
13681360

1369-
// Invalidate iterator since later on if we are not evicting this
1370-
// item, we may need to rely on the handle we created above to ensure
1371-
// proper cleanup if the item's raw refcount has dropped to 0.
1372-
// And since this item may be a parent item that has some child items
1373-
// in this very same mmContainer, we need to make sure we drop this
1374-
// exclusive iterator so we can gain access to it when we're cleaning
1375-
// up the child items
1376-
itr.destroy();
1377-
13781361
// Ensure that there are no accessors after removing from the access
13791362
// container
13801363
XDCHECK(evictHandle->getRefCount() == 1);
@@ -1388,12 +1371,10 @@ CacheAllocator<CacheTrait>::advanceIteratorAndTryEvictRegularItem(
13881371

13891372
template <typename CacheTrait>
13901373
typename CacheAllocator<CacheTrait>::WriteHandle
1391-
CacheAllocator<CacheTrait>::advanceIteratorAndTryEvictChainedItem(
1392-
EvictionIterator& itr) {
1393-
XDCHECK(itr->isChainedItem());
1374+
CacheAllocator<CacheTrait>::tryEvictChainedItem(Item& item) {
1375+
XDCHECK(item.isChainedItem());
13941376

1395-
ChainedItem* candidate = &itr->asChainedItem();
1396-
++itr;
1377+
ChainedItem* candidate = &item.asChainedItem();
13971378

13981379
// The parent could change at any point through transferChain. However, if
13991380
// that happens, we would realize that the releaseBackToAllocator return
@@ -1420,23 +1401,11 @@ CacheAllocator<CacheTrait>::advanceIteratorAndTryEvictChainedItem(
14201401
return parentHandle;
14211402
}
14221403

1423-
// Invalidate iterator since later on we may use the mmContainer
1424-
// associated with this iterator which cannot be done unless we
1425-
// drop this iterator
1426-
//
1427-
// This must be done once we know the parent is not nullptr.
1428-
// Since we can very well be the last holder of this parent item,
1429-
// which may have a chained item that is linked in this MM container.
1430-
itr.destroy();
1431-
14321404
// Ensure we have the correct parent and we're the only user of the
14331405
// parent, then free it from access container. Otherwise, we abort
14341406
XDCHECK_EQ(reinterpret_cast<uintptr_t>(&parent),
14351407
reinterpret_cast<uintptr_t>(parentHandle.get()));
14361408
XDCHECK_EQ(1u, parent.getRefCount());
1437-
1438-
removeFromMMContainer(*parentHandle);
1439-
14401409
XDCHECK(!parent.isInMMContainer());
14411410
XDCHECK(!parent.isAccessible());
14421411

cachelib/allocator/CacheAllocator.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1580,24 +1580,22 @@ class CacheAllocator : public CacheBase {
15801580

15811581
using EvictionIterator = typename MMContainer::Iterator;
15821582

1583-
// Advance the current iterator and try to evict a regular item
1583+
// Try to evict a regular item.
15841584
//
15851585
// @param mmContainer the container to look for evictions.
1586-
// @param itr iterator holding the item
1586+
// @param item item to evict
15871587
//
15881588
// @return valid handle to regular item on success. This will be the last
15891589
// handle to the item. On failure an empty handle.
1590-
WriteHandle advanceIteratorAndTryEvictRegularItem(MMContainer& mmContainer,
1591-
EvictionIterator& itr);
1590+
WriteHandle tryEvictRegularItem(MMContainer& mmContainer, Item& item);
15921591

1593-
// Advance the current iterator and try to evict a chained item
1594-
// Iterator may also be reset during the course of this function
1592+
// Try to evict a chained item.
15951593
//
1596-
// @param itr iterator holding the item
1594+
// @param item item to evict
15971595
//
15981596
// @return valid handle to the parent item on success. This will be the last
15991597
// handle to the item
1600-
WriteHandle advanceIteratorAndTryEvictChainedItem(EvictionIterator& itr);
1598+
WriteHandle tryEvictChainedItem(Item& item);
16011599

16021600
// Deserializer CacheAllocatorMetadata and verify the version
16031601
//

0 commit comments

Comments
 (0)