Skip to content

Commit 2d80fb1

Browse files
vinser52byrnedj
authored andcommitted
Fix moveRegularItemWithSync and add tests
(updated for numa bindings - post combined locking)
1 parent 62b69f2 commit 2d80fb1

File tree

2 files changed

+96
-0
lines changed

2 files changed

+96
-0
lines changed

cachelib/allocator/tests/AllocatorMemoryTiersTest.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ using LruAllocatorMemoryTiersTest = AllocatorMemoryTiersTest<LruAllocator>;
2626
TEST_F(LruAllocatorMemoryTiersTest, MultiTiersInvalid) { this->testMultiTiersInvalid(); }
2727
TEST_F(LruAllocatorMemoryTiersTest, MultiTiersValid) { this->testMultiTiersValid(); }
2828
TEST_F(LruAllocatorMemoryTiersTest, MultiTiersValidMixed) { this->testMultiTiersValidMixed(); }
29+
TEST_F(LruAllocatorMemoryTiersTest, MultiTiersRemoveDuringEviction) { this->testMultiTiersRemoveDuringEviction(); }
30+
TEST_F(LruAllocatorMemoryTiersTest, MultiTiersReplaceDuringEviction) { this->testMultiTiersReplaceDuringEviction(); }
2931

3032
} // end of namespace tests
3133
} // end of namespace cachelib

cachelib/allocator/tests/AllocatorMemoryTiersTest.h

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,42 @@
2020
#include "cachelib/allocator/MemoryTierCacheConfig.h"
2121
#include "cachelib/allocator/tests/TestBase.h"
2222

23+
#include <folly/synchronization/Latch.h>
24+
2325
namespace facebook {
2426
namespace cachelib {
2527
namespace tests {
2628

2729
template <typename AllocatorT>
2830
class AllocatorMemoryTiersTest : public AllocatorTest<AllocatorT> {
31+
private:
32+
template<typename MvCallback>
33+
void testMultiTiersAsyncOpDuringMove(std::unique_ptr<AllocatorT>& alloc,
34+
PoolId& pool, bool& quit, MvCallback&& moveCb) {
35+
typename AllocatorT::Config config;
36+
config.setCacheSize(4 * Slab::kSize);
37+
config.enableCachePersistence("/tmp");
38+
config.configureMemoryTiers({
39+
MemoryTierCacheConfig::fromShm()
40+
.setRatio(1).setMemBind(std::string("0")),
41+
MemoryTierCacheConfig::fromShm()
42+
.setRatio(1).setMemBind(std::string("0"))
43+
});
44+
45+
config.enableMovingOnSlabRelease(moveCb, {} /* ChainedItemsMoveSync */,
46+
-1 /* movingAttemptsLimit */);
47+
48+
alloc = std::make_unique<AllocatorT>(AllocatorT::SharedMemNew, config);
49+
ASSERT(alloc != nullptr);
50+
pool = alloc->addPool("default", alloc->getCacheMemoryStats().cacheSize);
51+
52+
int i = 0;
53+
while(!quit) {
54+
auto handle = alloc->allocate(pool, std::to_string(++i), std::string("value").size());
55+
ASSERT(handle != nullptr);
56+
ASSERT_NO_THROW(alloc->insertOrReplace(handle));
57+
}
58+
}
2959
public:
3060
void testMultiTiersInvalid() {
3161
typename AllocatorT::Config config;
@@ -74,6 +104,70 @@ class AllocatorMemoryTiersTest : public AllocatorTest<AllocatorT> {
74104
ASSERT(handle != nullptr);
75105
ASSERT_NO_THROW(alloc->insertOrReplace(handle));
76106
}
107+
108+
void testMultiTiersRemoveDuringEviction() {
109+
std::unique_ptr<AllocatorT> alloc;
110+
PoolId pool;
111+
std::unique_ptr<std::thread> t;
112+
folly::Latch latch(1);
113+
bool quit = false;
114+
115+
auto moveCb = [&] (typename AllocatorT::Item& oldItem,
116+
typename AllocatorT::Item& newItem,
117+
typename AllocatorT::Item* /* parentPtr */) {
118+
119+
auto key = oldItem.getKey();
120+
t = std::make_unique<std::thread>([&](){
121+
// remove() function is blocked by wait context
122+
// till item is moved to next tier. So that, we should
123+
// notify latch before calling remove()
124+
latch.count_down();
125+
alloc->remove(key);
126+
});
127+
// wait till async thread is running
128+
latch.wait();
129+
memcpy(newItem.getMemory(), oldItem.getMemory(), oldItem.getSize());
130+
quit = true;
131+
};
132+
133+
testMultiTiersAsyncOpDuringMove(alloc, pool, quit, moveCb);
134+
135+
t->join();
136+
}
137+
138+
void testMultiTiersReplaceDuringEviction() {
139+
std::unique_ptr<AllocatorT> alloc;
140+
PoolId pool;
141+
std::unique_ptr<std::thread> t;
142+
folly::Latch latch(1);
143+
bool quit = false;
144+
145+
auto moveCb = [&] (typename AllocatorT::Item& oldItem,
146+
typename AllocatorT::Item& newItem,
147+
typename AllocatorT::Item* /* parentPtr */) {
148+
auto key = oldItem.getKey();
149+
if(!quit) {
150+
// we need to replace only once because subsequent allocate calls
151+
// will cause evictions recursevly
152+
quit = true;
153+
t = std::make_unique<std::thread>([&](){
154+
auto handle = alloc->allocate(pool, key, std::string("new value").size());
155+
// insertOrReplace() function is blocked by wait context
156+
// till item is moved to next tier. So that, we should
157+
// notify latch before calling insertOrReplace()
158+
latch.count_down();
159+
ASSERT_NO_THROW(alloc->insertOrReplace(handle));
160+
});
161+
// wait till async thread is running
162+
latch.wait();
163+
}
164+
memcpy(newItem.getMemory(), oldItem.getMemory(), oldItem.getSize());
165+
};
166+
167+
testMultiTiersAsyncOpDuringMove(alloc, pool, quit, moveCb);
168+
169+
t->join();
170+
}
77171
};
78172
} // namespace tests
79173
} // namespace cachelib

0 commit comments

Comments
 (0)