Skip to content

Commit ea71c98

Browse files
byrnedjvinser52
authored andcommitted
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 9d1cfc7 commit ea71c98

File tree

9 files changed

+227
-68
lines changed

9 files changed

+227
-68
lines changed

cachelib/allocator/CacheAllocator-inl.h

Lines changed: 156 additions & 48 deletions
Large diffs are not rendered by default.

cachelib/allocator/CacheAllocator.h

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1565,6 +1565,26 @@ class CacheAllocator : public CacheBase {
15651565
// if the item is invalid
15661566
WriteHandle allocateChainedItemInternal(const Item& parent, uint32_t size);
15671567

1568+
// Allocate a chained item to a specific tier
1569+
//
1570+
// The resulting chained item does not have a parent item yet
1571+
// and if we fail to link to the chain for any reasoin
1572+
// the chained item will be freed once the handle is dropped.
1573+
//
1574+
// The parent item parameter here is mainly used to find the
1575+
// correct pool to allocate memory for this chained item
1576+
//
1577+
// @param parent parent item
1578+
// @param size the size for the chained allocation
1579+
// @param tid the tier to allocate on
1580+
//
1581+
// @return handle to the chained allocation
1582+
// @throw std::invalid_argument if the size requested is invalid or
1583+
// if the item is invalid
1584+
WriteHandle allocateChainedItemInternalTier(const Item& parent,
1585+
uint32_t size,
1586+
TierId tid);
1587+
15681588
// Given an existing item, allocate a new one for the
15691589
// existing one to later be moved into.
15701590
//
@@ -1669,9 +1689,8 @@ class CacheAllocator : public CacheBase {
16691689
// will be unmarked as having chained allocations. Parent will not be null
16701690
// after calling this API.
16711691
//
1672-
// Parent and NewParent must be valid handles to items with same key and
1673-
// parent must have chained items and parent handle must be the only
1674-
// outstanding handle for parent. New parent must be without any chained item
1692+
// NewParent must be valid handles to item with same key as Parent and
1693+
// Parent must have chained items. New parent must be without any chained item
16751694
// handles.
16761695
//
16771696
// Chained item lock for the parent's key needs to be held in exclusive mode.

cachelib/allocator/tests/BaseAllocatorTest.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4917,7 +4917,7 @@ class BaseAllocatorTest : public AllocatorTest<AllocatorT> {
49174917

49184918
std::memcpy(newItem.getMemory(), oldItem.getMemory(), oldItem.getSize());
49194919
++numMoves;
4920-
});
4920+
}, {}, 1000000 /* lots of moving tries */);
49214921

49224922
AllocatorT alloc(config);
49234923
const size_t numBytes = alloc.getCacheMemoryStats().ramCacheSize;
@@ -4958,15 +4958,15 @@ class BaseAllocatorTest : public AllocatorTest<AllocatorT> {
49584958
}
49594959

49604960
/* sleep override */
4961-
std::this_thread::sleep_for(std::chrono::milliseconds(100));
4961+
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
49624962
}
49634963
};
49644964

49654965
// Release 5 slabs
49664966
auto releaseFn = [&] {
49674967
for (unsigned int i = 0; i < 5;) {
49684968
/* sleep override */
4969-
std::this_thread::sleep_for(std::chrono::milliseconds(100));
4969+
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
49704970

49714971
ClassId cid = static_cast<ClassId>(i);
49724972
alloc.releaseSlab(pid, cid, SlabReleaseMode::kRebalance);
@@ -5126,7 +5126,7 @@ class BaseAllocatorTest : public AllocatorTest<AllocatorT> {
51265126
auto releaseFn = [&] {
51275127
for (unsigned int i = 0; i < 5;) {
51285128
/* sleep override */
5129-
std::this_thread::sleep_for(std::chrono::milliseconds(100));
5129+
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
51305130

51315131
ClassId cid = static_cast<ClassId>(i);
51325132
alloc.releaseSlab(pid, cid, SlabReleaseMode::kRebalance);
@@ -5969,7 +5969,6 @@ class BaseAllocatorTest : public AllocatorTest<AllocatorT> {
59695969
EXPECT_EQ(nullptr,
59705970
util::allocateAccessible(alloc, poolId, "large", largeSize));
59715971

5972-
std::this_thread::sleep_for(std::chrono::seconds{1});
59735972
// trigger the slab rebalance
59745973
EXPECT_EQ(nullptr,
59755974
util::allocateAccessible(alloc, poolId, "large", largeSize));

cachelib/allocator/tests/RebalanceStrategyTest.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,9 @@ class RebalanceStrategyTest : public testing::Test {
214214
config.poolRebalancerFreeAllocThreshold = 20;
215215

216216
initAllocatorConfigForStrategy(config, LruTailAge);
217+
//TODO: why does this fail with orig. value of 8?
218+
//on upstream this fails too, it always reports 4 instead
219+
//of the original test value, which is 8 expected slabs
217220
doWork(config, true, 8);
218221
}
219222

cachelib/allocator/tests/RefCountTest.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -209,16 +209,6 @@ void RefCountTest::testMarkForEvictionAndMoving() {
209209
ASSERT_EQ(ret, 0);
210210
}
211211

212-
{
213-
// cannot mark moving when ref count > 0
214-
RefcountWithFlags ref;
215-
ref.markInMMContainer();
216-
217-
ref.incRef();
218-
219-
ASSERT_FALSE(ref.markMoving());
220-
}
221-
222212
{
223213
// cannot mark for eviction when ref count > 0
224214
RefcountWithFlags ref;

cachelib/allocator/tests/SimpleRebalancingTest.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ class SimpleRebalanceTest : public testing::Test {
104104

105105
// Sleep for 2 seconds to let the rebalancing work
106106
/* sleep override */
107-
std::this_thread::sleep_for(std::chrono::seconds(3));
107+
std::this_thread::sleep_for(std::chrono::seconds(10));
108108

109109
// Evicted keys shouldn't be in the allocator anymore
110110
ASSERT_FALSE(evictedKeys.empty());

cachelib/cachebench/runner/CacheStressor.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class CacheStressor : public Stressor {
7777
std::unique_lock<folly::SharedMutex> lock;
7878

7979
CacheStressSyncObj(CacheStressor& s, std::string itemKey)
80-
: lock{s.chainedItemAcquireUniqueLock(itemKey)} {}
80+
: lock{s.chainedItemTryAcquireUniqueLock(itemKey)} {}
8181
};
8282
movingSync = [this](typename CacheT::Item::Key key) {
8383
return std::make_unique<CacheStressSyncObj>(*this, key.str());
@@ -247,6 +247,10 @@ class CacheStressor : public Stressor {
247247
using Lock = std::unique_lock<folly::SharedMutex>;
248248
return lockEnabled_ ? Lock{getLock(key)} : Lock{};
249249
}
250+
auto chainedItemTryAcquireUniqueLock(Key key) {
251+
using Lock = std::unique_lock<folly::SharedMutex>;
252+
return lockEnabled_ ? Lock{getLock(key), std::try_to_lock} : Lock{};
253+
}
250254

251255
// populate the input item handle according to the stress setup.
252256
void populateItem(WriteHandle& handle, const std::string& itemValue = "") {
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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" : 20000000,
25+
"numThreads" : 32,
26+
"numKeys" : 250000,
27+
"generator": "online",
28+
"keySizeRange" : [1, 8, 32, 64, 128, 256, 512],
29+
"keySizeRangeProbability" : [0.1, 0.1, 0.2, 0.2, 0.3, 0.1],
30+
"valSizeRange" : [1, 128, 512, 1024, 4096, 10240, 20480, 40960, 60000],
31+
"valSizeRangeProbability" : [0.1, 0.1, 0.1, 0.2, 0.2, 0.1, 0.1, 0.1],
32+
"getRatio" : 0.70,
33+
"setRatio" : 0.30
34+
}
35+
}

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+
../bin/cachebench --json_test_config ../test_configs/small_moving_bg.json

0 commit comments

Comments
 (0)