Skip to content

Commit d51fade

Browse files
igchorbyrnedj
authored andcommitted
Remove parameter for markMoving()
1 parent 773d548 commit d51fade

File tree

7 files changed

+72
-48
lines changed

7 files changed

+72
-48
lines changed

cachelib/allocator/CacheAllocator-inl.h

Lines changed: 17 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1303,19 +1303,6 @@ size_t CacheAllocator<CacheTrait>::wakeUpWaitersLocked(folly::StringPiece key,
13031303
template <typename CacheTrait>
13041304
bool CacheAllocator<CacheTrait>::moveRegularItemWithSync(
13051305
Item& oldItem, WriteHandle& newItemHdl) {
1306-
//on function exit - the new item handle is no longer moving
1307-
//and other threads may access it - but in case where
1308-
//we failed to replace in access container we can give the
1309-
//new item back to the allocator
1310-
auto guard = folly::makeGuard([&]() {
1311-
auto ref = newItemHdl->unmarkMoving();
1312-
if (UNLIKELY(ref == 0)) {
1313-
const auto res =
1314-
releaseBackToAllocator(*newItemHdl, RemoveContext::kNormal, false);
1315-
XDCHECK(res == ReleaseRes::kReleased);
1316-
}
1317-
});
1318-
13191306
XDCHECK(oldItem.isMoving());
13201307
XDCHECK(!oldItem.isExpired());
13211308
// TODO: should we introduce new latency tracker. E.g. evictRegularLatency_
@@ -1330,20 +1317,26 @@ bool CacheAllocator<CacheTrait>::moveRegularItemWithSync(
13301317
newItemHdl->markNvmClean();
13311318
}
13321319

1333-
// mark new item as moving to block readers until the data is copied
1334-
// (moveCb is called). Mark item in MMContainer temporarily (TODO: should
1335-
// we remove markMoving requirement for the item to be linked?)
1336-
newItemHdl->markInMMContainer();
1337-
auto marked = newItemHdl->markMoving(false /* there is already a handle */);
1338-
newItemHdl->unmarkInMMContainer();
1339-
XDCHECK(marked);
1340-
13411320
auto predicate = [&](const Item& item){
13421321
// we rely on moving flag being set (it should block all readers)
13431322
XDCHECK(item.getRefCount() == 0);
13441323
return true;
13451324
};
13461325

1326+
if (config_.moveCb) {
1327+
// Execute the move callback. We cannot make any guarantees about the
1328+
// consistency of the old item beyond this point, because the callback can
1329+
// do more than a simple memcpy() e.g. update external references. If there
1330+
// are any remaining handles to the old item, it is the caller's
1331+
// responsibility to invalidate them. The move can only fail after this
1332+
// statement if the old item has been removed or replaced, in which case it
1333+
// should be fine for it to be left in an inconsistent state.
1334+
config_.moveCb(oldItem, *newItemHdl, nullptr);
1335+
} else {
1336+
std::memcpy(newItemHdl->getMemory(), oldItem.getMemory(),
1337+
oldItem.getSize());
1338+
}
1339+
13471340
auto replaced = accessContainer_->replaceIf(oldItem, *newItemHdl,
13481341
predicate);
13491342
// another thread may have called insertOrReplace which could have
@@ -1363,26 +1356,13 @@ bool CacheAllocator<CacheTrait>::moveRegularItemWithSync(
13631356
// 3. replaced handle is returned and eventually drops
13641357
// ref to 0 and the item is recycled back to allocator.
13651358

1366-
if (config_.moveCb) {
1367-
// Execute the move callback. We cannot make any guarantees about the
1368-
// consistency of the old item beyond this point, because the callback can
1369-
// do more than a simple memcpy() e.g. update external references. If there
1370-
// are any remaining handles to the old item, it is the caller's
1371-
// responsibility to invalidate them. The move can only fail after this
1372-
// statement if the old item has been removed or replaced, in which case it
1373-
// should be fine for it to be left in an inconsistent state.
1374-
config_.moveCb(oldItem, *newItemHdl, nullptr);
1375-
} else {
1376-
std::memcpy(newItemHdl->getMemory(), oldItem.getMemory(),
1377-
oldItem.getSize());
1378-
}
1379-
13801359
// Adding the item to mmContainer has to succeed since no one can remove the item
13811360
auto& newContainer = getMMContainer(*newItemHdl);
13821361
auto mmContainerAdded = newContainer.add(*newItemHdl);
13831362
XDCHECK(mmContainerAdded);
13841363

13851364
// no one can add or remove chained items at this point
1365+
// TODO: is this race? new Item is already accessible but not yet marked with hasChainedItem()
13861366
if (oldItem.hasChainedItem()) {
13871367
// safe to acquire handle for a moving Item
13881368
auto incRes = incRef(oldItem, false);
@@ -1612,7 +1592,7 @@ CacheAllocator<CacheTrait>::findEviction(TierId tid, PoolId pid, ClassId cid) {
16121592
if (lastTier && shouldWriteToNvmCache(*candidate_) && !token.isValid()) {
16131593
stats_.evictFailConcurrentFill.inc();
16141594
} else if ( (lastTier && candidate_->markForEviction()) ||
1615-
(!lastTier && candidate_->markMoving(true)) ) {
1595+
(!lastTier && candidate_->markMoving()) ) {
16161596
XDCHECK(candidate_->isMoving() || candidate_->isMarkedForEviction());
16171597
// markForEviction to make sure no other thead is evicting the item
16181598
// nor holding a handle to that item if this is last tier
@@ -3499,10 +3479,7 @@ bool CacheAllocator<CacheTrait>::markMovingForSlabRelease(
34993479
// Since this callback is executed, the item is not yet freed
35003480
itemFreed = false;
35013481
Item* item = static_cast<Item*>(memory);
3502-
// TODO: for chained items, moving bit is only used to avoid
3503-
// freeing the item prematurely
3504-
auto failIfRefNotZero = numTiers > 1 && !item->isChainedItem();
3505-
if (item->markMoving(failIfRefNotZero)) {
3482+
if (item->markMoving()) {
35063483
markedMoving = true;
35073484
}
35083485
};

cachelib/allocator/CacheAllocator.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1979,7 +1979,7 @@ auto& mmContainer = getMMContainer(tid, pid, cid);
19791979
throw std::runtime_error("Not supported for chained items");
19801980
}
19811981

1982-
if (candidate->markMoving(true)) {
1982+
if (candidate->markMoving()) {
19831983
mmContainer.remove(itr);
19841984
candidates.push_back(candidate);
19851985
} else {
@@ -2052,7 +2052,7 @@ auto& mmContainer = getMMContainer(tid, pid, cid);
20522052

20532053
// TODO: only allow it for read-only items?
20542054
// or implement mvcc
2055-
if (candidate->markMoving(true)) {
2055+
if (candidate->markMoving()) {
20562056
// promotions should rarely fail since we already marked moving
20572057
mmContainer.remove(itr);
20582058
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: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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/Refcount.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -320,12 +320,18 @@ class FOLLY_PACK_ATTR RefcountWithFlags {
320320
*
321321
* Unmarking moving does not depend on `isInMMContainer`
322322
*/
323-
bool markMoving(bool failIfRefNotZero) {
324-
auto predicate = [failIfRefNotZero](const Value curValue) {
323+
bool markMoving() {
324+
auto predicate = [](const Value curValue) {
325325
Value conditionBitMask = getAdminRef<kLinked>();
326326
const bool flagSet = curValue & conditionBitMask;
327327
const bool alreadyExclusive = curValue & getAdminRef<kExclusive>();
328-
if (failIfRefNotZero && (curValue & kAccessRefMask) != 0) {
328+
const bool isChained = curValue & getFlag<kIsChainedItem>();
329+
330+
// chained item can have ref count == 1, this just means it's linked in the chain
331+
if (isChained && (curValue & kAccessRefMask) > 1) {
332+
return false;
333+
}
334+
if ((curValue & kAccessRefMask) != 0) {
329335
return false;
330336
}
331337
if (!flagSet || alreadyExclusive) {
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// @nolint like default.json, but moves items during slab release instead of evicting them.
2+
{
3+
"cache_config" : {
4+
"cacheSizeMB" : 2248,
5+
"cacheDir": "/tmp/mem-tier5",
6+
"memoryTiers" : [
7+
{
8+
"ratio": 1,
9+
"memBindNodes": 0
10+
}, {
11+
"ratio": 1,
12+
"memBindNodes": 0
13+
}
14+
],
15+
"poolRebalanceIntervalSec" : 1,
16+
"moveOnSlabRelease" : true,
17+
"rebalanceMinSlabs" : 2,
18+
"evictorThreads": 2,
19+
"promoterThreads": 2
20+
},
21+
"test_config" :
22+
{
23+
"preallocateCache" : true,
24+
"numOps" : 40000000,
25+
"numThreads" : 32,
26+
"numKeys" : 250000,
27+
"generator": "online",
28+
29+
"keySizeRange" : [1, 8, 32, 64, 128, 256, 512],
30+
"keySizeRangeProbability" : [0.1, 0.1, 0.2, 0.2, 0.3, 0.1],
31+
32+
"valSizeRange" : [1, 128, 512, 1024, 4096, 10240, 20480, 40960, 60000],
33+
"valSizeRangeProbability" : [0.1, 0.1, 0.1, 0.2, 0.2, 0.1, 0.1, 0.1],
34+
35+
"getRatio" : 0.70,
36+
"setRatio" : 0.30
37+
}
38+
39+
}
40+

run_tests.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ fi
1313

1414
../bin/cachebench --json_test_config ../test_configs/consistency/navy.json
1515
../bin/cachebench --json_test_config ../test_configs/consistency/navy-multi-tier.json
16+
../opt/bin/cachebench --json_test_config /opt/test_configs/small_moving_bg.json

0 commit comments

Comments
 (0)