Skip to content

Commit 98a2fde

Browse files
committed
Extend cachbench with touch value
The main purpose of this patch is to better simulate workloads in cachebench. Setting touchValue to true allows to see performance impact of using different mediums for memory cache.
1 parent 681bcbc commit 98a2fde

File tree

5 files changed

+28
-39
lines changed

5 files changed

+28
-39
lines changed

cachelib/cachebench/cache/Cache-inl.h

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,10 @@ uint64_t Cache<Allocator>::fetchNandWrites() const {
5050
template <typename Allocator>
5151
Cache<Allocator>::Cache(const CacheConfig& config,
5252
ChainedItemMovingSync movingSync,
53-
std::string cacheDir)
53+
std::string cacheDir,
54+
bool touchValue)
5455
: config_(config),
56+
touchValue_(touchValue),
5557
nandBytesBegin_{fetchNandWrites()},
5658
itemRecords_(config_.enableItemDestructorCheck) {
5759
constexpr size_t MB = 1024ULL * 1024ULL;
@@ -325,22 +327,13 @@ template <typename Allocator>
325327
void Cache<Allocator>::enableConsistencyCheck(
326328
const std::vector<std::string>& keys) {
327329
XDCHECK(valueTracker_ == nullptr);
328-
XDCHECK(!valueValidatingEnabled());
329330
valueTracker_ =
330331
std::make_unique<ValueTracker>(ValueTracker::wrapStrings(keys));
331332
for (const std::string& key : keys) {
332333
invalidKeys_[key] = false;
333334
}
334335
}
335336

336-
template <typename Allocator>
337-
void Cache<Allocator>::enableValueValidating(
338-
const std::string &expectedValue) {
339-
XDCHECK(!valueValidatingEnabled());
340-
XDCHECK(!consistencyCheckEnabled());
341-
this->expectedValue_ = expectedValue;
342-
}
343-
344337
template <typename Allocator>
345338
typename Cache<Allocator>::RemoveRes Cache<Allocator>::remove(Key key) {
346339
if (!consistencyCheckEnabled()) {
@@ -434,17 +427,15 @@ typename Cache<Allocator>::ItemHandle Cache<Allocator>::insertOrReplace(
434427
}
435428

436429
template <typename Allocator>
437-
void Cache<Allocator>::validateValue(const ItemHandle &it) const {
438-
XDCHECK(valueValidatingEnabled());
439-
440-
const auto &expected = expectedValue_.value();
430+
void Cache<Allocator>::touchValue(const ItemHandle& it) const {
431+
XDCHECK(touchValueEnabled());
441432

442433
auto ptr = reinterpret_cast<const uint8_t*>(getMemory(it));
443-
auto cmp = std::memcmp(ptr, expected.data(), std::min<size_t>(expected.size(),
444-
getSize(it)));
445-
if (cmp != 0) {
446-
throw std::runtime_error("Value does not match!");
447-
}
434+
435+
/* The accumulate call is intended to access all bytes of the value
436+
* and nothing more. */
437+
auto sum = std::accumulate(ptr, ptr + getSize(it), 0ULL);
438+
folly::doNotOptimizeAway(sum);
448439
}
449440

450441
template <typename Allocator>
@@ -459,9 +450,8 @@ typename Cache<Allocator>::ItemHandle Cache<Allocator>::find(Key key,
459450
auto it = cache_->find(key, mode);
460451
it.wait();
461452

462-
if (valueValidatingEnabled()) {
463-
XDCHECK(!consistencyCheckEnabled());
464-
validateValue(it);
453+
if (touchValueEnabled()) {
454+
touchValue(it);
465455
}
466456

467457
return it;
@@ -472,8 +462,6 @@ typename Cache<Allocator>::ItemHandle Cache<Allocator>::find(Key key,
472462
return it;
473463
}
474464

475-
XDCHECK(!valueValidatingEnabled());
476-
477465
auto opId = valueTracker_->beginGet(key);
478466
auto it = findFn();
479467
if (checkGet(opId, it)) {

cachelib/cachebench/cache/Cache.h

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,11 @@ class Cache {
6464
// cache.
6565
// @param cacheDir optional directory for the cache to enable
6666
// persistence across restarts.
67+
// @param touchValue read entire value on find
6768
explicit Cache(const CacheConfig& config,
6869
ChainedItemMovingSync movingSync = {},
69-
std::string cacheDir = "");
70+
std::string cacheDir = "",
71+
bool touchValue = false);
7072

7173
~Cache();
7274

@@ -168,8 +170,8 @@ class Cache {
168170
return getSize(item.get());
169171
}
170172

171-
// checks if values stored in it matches expectedValue_.
172-
void validateValue(const ItemHandle &it) const;
173+
// read entire value on find.
174+
void touchValue(const ItemHandle& it) const;
173175

174176
// returns the size of the item, taking into account ItemRecords could be
175177
// enabled.
@@ -228,14 +230,11 @@ class Cache {
228230
// @param keys list of keys that the stressor uses for the workload.
229231
void enableConsistencyCheck(const std::vector<std::string>& keys);
230232

231-
// enables validating all values on find. Each value is compared to
232-
// expected Value.
233-
void enableValueValidating(const std::string &expectedValue);
234-
235233
// returns true if the consistency checking is enabled.
236234
bool consistencyCheckEnabled() const { return valueTracker_ != nullptr; }
237235

238-
bool valueValidatingEnabled() const { return expectedValue_.has_value(); }
236+
// returns true if touching value is enabled.
237+
bool touchValueEnabled() const { return touchValue_; }
239238

240239
// return true if the key was previously detected to be inconsistent. This
241240
// is useful only when consistency checking is enabled by calling
@@ -359,8 +358,8 @@ class Cache {
359358
// tracker for consistency monitoring.
360359
std::unique_ptr<ValueTracker> valueTracker_;
361360

362-
// exceptected value of all items in Cache.
363-
std::optional<std::string> expectedValue_;
361+
// read entire value on find.
362+
bool touchValue_{false};
364363

365364
// reading of the nand bytes written for the benchmark if enabled.
366365
const uint64_t nandBytesBegin_{0};

cachelib/cachebench/runner/CacheStressor.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ class CacheStressor : public Stressor {
9393
cacheConfig.ticker = ticker_;
9494
}
9595

96-
cache_ = std::make_unique<CacheT>(cacheConfig, movingSync);
96+
cache_ = std::make_unique<CacheT>(cacheConfig, movingSync, "",
97+
config_.touchValue);
9798
if (config_.opPoolDistribution.size() > cache_->numPools()) {
9899
throw std::invalid_argument(folly::sformat(
99100
"more pools specified in the test than in the cache. "
@@ -110,9 +111,6 @@ class CacheStressor : public Stressor {
110111
if (config_.checkConsistency) {
111112
cache_->enableConsistencyCheck(wg_->getAllKeys());
112113
}
113-
if (config_.validateValue) {
114-
cache_->enableValueValidating(hardcodedString_);
115-
}
116114
if (config_.opRatePerSec > 0) {
117115
rateLimiter_ = std::make_unique<folly::BasicTokenBucket<>>(
118116
config_.opRatePerSec, config_.opRatePerSec);

cachelib/cachebench/util/Config.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ StressorConfig::StressorConfig(const folly::dynamic& configJson) {
3434
JSONSetVal(configJson, samplingIntervalMs);
3535

3636
JSONSetVal(configJson, checkConsistency);
37-
JSONSetVal(configJson, validateValue);
37+
JSONSetVal(configJson, touchValue);
3838

3939
JSONSetVal(configJson, numOps);
4040
JSONSetVal(configJson, numThreads);

cachelib/cachebench/util/Config.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,10 @@ struct StressorConfig : public JSONConfig {
195195
// Mutually exclusive with checkConsistency
196196
bool validateValue{false};
197197

198+
// If enabled, each value will be read on find. This is useful for measuring
199+
// performance of value access.
200+
bool touchValue{false};
201+
198202
uint64_t numOps{0}; // operation per thread
199203
uint64_t numThreads{0}; // number of threads that will run
200204
uint64_t numKeys{0}; // number of keys that will be used

0 commit comments

Comments
 (0)