Skip to content

Commit 09d7bab

Browse files
committed
Chained item movement between tiers - sync on the parent item (#84)
* Chained item movement between tiers - currently sync on the parent item for moving. - updated tests accordingly, note that we can no longer swap parent item if chained item is being moved for slab release. * added some debug checks around chained item check * fix slab release behavior if no movecb
1 parent 5632d18 commit 09d7bab

21 files changed

+621
-525
lines changed

cachelib/allocator/CacheAllocator-inl.h

Lines changed: 438 additions & 430 deletions
Large diffs are not rendered by default.

cachelib/allocator/CacheAllocator.h

Lines changed: 49 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1394,7 +1394,7 @@ class CacheAllocator : public CacheBase {
13941394

13951395
private:
13961396
// wrapper around Item's refcount and active handle tracking
1397-
FOLLY_ALWAYS_INLINE RefcountWithFlags::incResult incRef(Item& it, bool failIfMoving);
1397+
FOLLY_ALWAYS_INLINE RefcountWithFlags::incResult incRef(Item& it);
13981398
FOLLY_ALWAYS_INLINE RefcountWithFlags::Value decRef(Item& it);
13991399

14001400
// drops the refcount and if needed, frees the allocation back to the memory
@@ -1552,6 +1552,26 @@ class CacheAllocator : public CacheBase {
15521552
WriteHandle allocateChainedItemInternal(const ReadHandle& parent,
15531553
uint32_t size);
15541554

1555+
// Allocate a chained item to a specific tier
1556+
//
1557+
// The resulting chained item does not have a parent item yet
1558+
// and if we fail to link to the chain for any reasoin
1559+
// the chained item will be freed once the handle is dropped.
1560+
//
1561+
// The parent item parameter here is mainly used to find the
1562+
// correct pool to allocate memory for this chained item
1563+
//
1564+
// @param parent parent item
1565+
// @param size the size for the chained allocation
1566+
// @param tid the tier to allocate on
1567+
//
1568+
// @return handle to the chained allocation
1569+
// @throw std::invalid_argument if the size requested is invalid or
1570+
// if the item is invalid
1571+
WriteHandle allocateChainedItemInternalTier(const Item& parent,
1572+
uint32_t size,
1573+
TierId tid);
1574+
15551575
// Given an item and its parentKey, validate that the parentKey
15561576
// corresponds to an item that's the parent of the supplied item.
15571577
//
@@ -1632,19 +1652,17 @@ class CacheAllocator : public CacheBase {
16321652
//
16331653
// @return true If the move was completed, and the containers were updated
16341654
// successfully.
1635-
bool moveRegularItemWithSync(Item& oldItem, WriteHandle& newItemHdl);
1655+
bool moveRegularItem(Item& oldItem, WriteHandle& newItemHdl);
16361656

1637-
// Moves a regular item to a different slab. This should only be used during
1638-
// slab release after the item's exclusive bit has been set. The user supplied
1639-
// callback is responsible for copying the contents and fixing the semantics
1640-
// of chained item.
1657+
// Moves a chained item to a different memory tier.
16411658
//
1642-
// @param oldItem item being moved
1659+
// @param oldItem Reference to the item being moved
16431660
// @param newItemHdl Reference to the handle of the new item being moved into
1661+
// @param parentHandle Reference to the handle of the parent item
16441662
//
16451663
// @return true If the move was completed, and the containers were updated
16461664
// successfully.
1647-
bool moveRegularItem(Item& oldItem, WriteHandle& newItemHdl);
1665+
bool moveChainedItem(ChainedItem& oldItem, WriteHandle& newItemHdl, Item& parentItem);
16481666

16491667
// template class for viewAsChainedAllocs that takes either ReadHandle or
16501668
// WriteHandle
@@ -1657,29 +1675,12 @@ class CacheAllocator : public CacheBase {
16571675
template <typename Handle>
16581676
folly::IOBuf convertToIOBufT(Handle& handle);
16591677

1660-
// Moves a chained item to a different slab. This should only be used during
1661-
// slab release after the item's exclusive bit has been set. The user supplied
1662-
// callback is responsible for copying the contents and fixing the semantics
1663-
// of chained item.
1664-
//
1665-
// Note: If we have successfully moved the old item into the new, the
1666-
// newItemHdl is reset and no longer usable by the caller.
1667-
//
1668-
// @param oldItem Reference to the item being moved
1669-
// @param newItemHdl Reference to the handle of the new item being
1670-
// moved into
1671-
//
1672-
// @return true If the move was completed, and the containers were updated
1673-
// successfully.
1674-
bool moveChainedItem(ChainedItem& oldItem, WriteHandle& newItemHdl);
1675-
16761678
// Transfers the chain ownership from parent to newParent. Parent
16771679
// will be unmarked as having chained allocations. Parent will not be null
16781680
// after calling this API.
16791681
//
1680-
// Parent and NewParent must be valid handles to items with same key and
1681-
// parent must have chained items and parent handle must be the only
1682-
// outstanding handle for parent. New parent must be without any chained item
1682+
// NewParent must be valid handles to item with same key as Parent and
1683+
// Parent must have chained items. New parent must be without any chained item
16831684
// handles.
16841685
//
16851686
// Chained item lock for the parent's key needs to be held in exclusive mode.
@@ -1688,7 +1689,7 @@ class CacheAllocator : public CacheBase {
16881689
// @param newParent the new parent for the chain
16891690
//
16901691
// @throw if any of the conditions for parent or newParent are not met.
1691-
void transferChainLocked(WriteHandle& parent, WriteHandle& newParent);
1692+
void transferChainLocked(Item& parent, WriteHandle& newParent);
16921693

16931694
// replace a chained item in the existing chain. This needs to be called
16941695
// with the chained item lock held exclusive
@@ -1702,6 +1703,24 @@ class CacheAllocator : public CacheBase {
17021703
WriteHandle newItemHdl,
17031704
const Item& parent);
17041705

1706+
//
1707+
// Performs the actual inplace replace - it is called from
1708+
// moveChainedItem and replaceChainedItemLocked
1709+
// must hold chainedItemLock
1710+
//
1711+
// @param oldItem the item we are replacing in the chain
1712+
// @param newItem the item we are replacing it with
1713+
// @param parent the parent for the chain
1714+
// @param fromMove used to determine if the replaced was called from
1715+
// moveChainedItem - we avoid the handle destructor
1716+
// in this case.
1717+
//
1718+
// @return handle to the oldItem
1719+
void replaceInChainLocked(Item& oldItem,
1720+
WriteHandle& newItemHdl,
1721+
const Item& parent,
1722+
bool fromMove);
1723+
17051724
// Insert an item into MM container. The caller must hold a valid handle for
17061725
// the item.
17071726
//
@@ -2016,7 +2035,7 @@ auto& mmContainer = getMMContainer(tid, pid, cid);
20162035
throw std::runtime_error("Not supported for chained items");
20172036
}
20182037

2019-
if (candidate->markMoving(true)) {
2038+
if (candidate->markMoving()) {
20202039
mmContainer.remove(itr);
20212040
candidates.push_back(candidate);
20222041
} else {
@@ -2089,7 +2108,7 @@ auto& mmContainer = getMMContainer(tid, pid, cid);
20892108

20902109
// TODO: only allow it for read-only items?
20912110
// or implement mvcc
2092-
if (candidate->markMoving(true)) {
2111+
if (candidate->markMoving()) {
20932112
// promotions should rarely fail since we already marked moving
20942113
mmContainer.remove(itr);
20952114
candidates.push_back(candidate);

cachelib/allocator/CacheItem-inl.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,8 @@ bool CacheItem<CacheTrait>::markForEvictionWhenMoving() {
238238
}
239239

240240
template <typename CacheTrait>
241-
bool CacheItem<CacheTrait>::markMoving(bool failIfRefNotZero) {
242-
return ref_.markMoving(failIfRefNotZero);
241+
bool CacheItem<CacheTrait>::markMoving() {
242+
return ref_.markMoving();
243243
}
244244

245245
template <typename CacheTrait>

cachelib/allocator/CacheItem.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -312,9 +312,9 @@ class CACHELIB_PACKED_ATTR CacheItem {
312312
//
313313
// @return true on success, failure if item is marked as exclusive
314314
// @throw exception::RefcountOverflow on ref count overflow
315-
FOLLY_ALWAYS_INLINE RefcountWithFlags::incResult incRef(bool failIfMoving) {
315+
FOLLY_ALWAYS_INLINE RefcountWithFlags::incResult incRef() {
316316
try {
317-
return ref_.incRef(failIfMoving);
317+
return ref_.incRef();
318318
} catch (exception::RefcountOverflow& e) {
319319
throw exception::RefcountOverflow(
320320
folly::sformat("{} item: {}", e.what(), toString()));
@@ -381,7 +381,7 @@ class CACHELIB_PACKED_ATTR CacheItem {
381381
* Unmarking moving will also return the refcount at the moment of
382382
* unmarking.
383383
*/
384-
bool markMoving(bool failIfRefNotZero);
384+
bool markMoving();
385385
RefcountWithFlags::Value unmarkMoving() noexcept;
386386
bool isMoving() const noexcept;
387387
bool isOnlyMoving() const noexcept;

cachelib/allocator/MM2Q-inl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,12 @@ MM2Q::Container<T, HookPtr>::getEvictionIterator() const noexcept {
247247
return LockedIterator{std::move(l), lru_.rbegin()};
248248
}
249249

250+
template <typename T, MM2Q::Hook<T> T::*HookPtr>
251+
template <typename F>
252+
void MM2Q::Container<T, HookPtr>::withContainerLock(F&& fun) {
253+
lruMutex_->lock_combine([this, &fun]() { fun(); });
254+
}
255+
250256
template <typename T, MM2Q::Hook<T> T::*HookPtr>
251257
template <typename F>
252258
void MM2Q::Container<T, HookPtr>::withEvictionIterator(F&& fun) {

cachelib/allocator/MM2Q.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,10 @@ class MM2Q {
503503
template <typename F>
504504
void withEvictionIterator(F&& f);
505505

506+
// Execute provided function under container lock.
507+
template <typename F>
508+
void withContainerLock(F&& f);
509+
506510
// Execute provided function under container lock. Function gets
507511
// iterator passed as parameter.
508512
template <typename F>

cachelib/allocator/MMLru-inl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,12 @@ MMLru::Container<T, HookPtr>::getEvictionIterator() const noexcept {
218218
return LockedIterator{std::move(l), lru_.rbegin()};
219219
}
220220

221+
template <typename T, MMLru::Hook<T> T::*HookPtr>
222+
template <typename F>
223+
void MMLru::Container<T, HookPtr>::withContainerLock(F&& fun) {
224+
lruMutex_->lock_combine([this, &fun]() { fun(); });
225+
}
226+
221227
template <typename T, MMLru::Hook<T> T::*HookPtr>
222228
template <typename F>
223229
void MMLru::Container<T, HookPtr>::withEvictionIterator(F&& fun) {

cachelib/allocator/MMLru.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,10 @@ class MMLru {
377377
template <typename F>
378378
void withEvictionIterator(F&& f);
379379

380+
// Execute provided function under container lock.
381+
template <typename F>
382+
void withContainerLock(F&& f);
383+
380384
template <typename F>
381385
void withPromotionIterator(F&& f);
382386

cachelib/allocator/MMTinyLFU-inl.h

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

223+
template <typename T, MMTinyLFU::Hook<T> T::*HookPtr>
224+
template <typename F>
225+
void MMTinyLFU::Container<T, HookPtr>::withContainerLock(F&& fun) {
226+
LockHolder l(lruMutex_);
227+
fun();
228+
}
229+
223230
template <typename T, MMTinyLFU::Hook<T> T::*HookPtr>
224231
template <typename F>
225232
void MMTinyLFU::Container<T, HookPtr>::withEvictionIterator(F&& fun) {

cachelib/allocator/MMTinyLFU.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,10 @@ class MMTinyLFU {
497497
template <typename F>
498498
void withEvictionIterator(F&& f);
499499

500+
// Execute provided function under container lock.
501+
template <typename F>
502+
void withContainerLock(F&& f);
503+
500504
template <typename F>
501505
void withPromotionIterator(F&& f);
502506

0 commit comments

Comments
 (0)