Skip to content

Commit 33162a7

Browse files
authored
Merge pull request #31 from igchor/validate_value
Extend cachbench with value validation
2 parents a043394 + ccc4f1c commit 33162a7

File tree

5 files changed

+51
-1
lines changed

5 files changed

+51
-1
lines changed

cachelib/cachebench/cache/Cache-inl.h

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,13 +327,22 @@ template <typename Allocator>
327327
void Cache<Allocator>::enableConsistencyCheck(
328328
const std::vector<std::string>& keys) {
329329
XDCHECK(valueTracker_ == nullptr);
330+
XDCHECK(!valueValidatingEnabled());
330331
valueTracker_ =
331332
std::make_unique<ValueTracker>(ValueTracker::wrapStrings(keys));
332333
for (const std::string& key : keys) {
333334
invalidKeys_[key] = false;
334335
}
335336
}
336337

338+
template <typename Allocator>
339+
void Cache<Allocator>::enableValueValidating(
340+
const std::string &expectedValue) {
341+
XDCHECK(!valueValidatingEnabled());
342+
XDCHECK(!consistencyCheckEnabled());
343+
this->expectedValue_ = expectedValue;
344+
}
345+
337346
template <typename Allocator>
338347
typename Cache<Allocator>::RemoveRes Cache<Allocator>::remove(Key key) {
339348
if (!consistencyCheckEnabled()) {
@@ -426,6 +435,20 @@ typename Cache<Allocator>::ItemHandle Cache<Allocator>::insertOrReplace(
426435
return rv;
427436
}
428437

438+
template <typename Allocator>
439+
void Cache<Allocator>::validateValue(const ItemHandle &it) const {
440+
XDCHECK(valueValidatingEnabled());
441+
442+
const auto &expected = expectedValue_.value();
443+
444+
auto ptr = reinterpret_cast<const uint8_t*>(getMemory(it));
445+
auto cmp = std::memcmp(ptr, expected.data(), std::min<size_t>(expected.size(),
446+
getSize(it)));
447+
if (cmp != 0) {
448+
throw std::runtime_error("Value does not match!");
449+
}
450+
}
451+
429452
template <typename Allocator>
430453
typename Cache<Allocator>::ItemHandle Cache<Allocator>::find(Key key,
431454
AccessMode mode) {
@@ -441,9 +464,15 @@ typename Cache<Allocator>::ItemHandle Cache<Allocator>::find(Key key,
441464
};
442465

443466
if (!consistencyCheckEnabled()) {
444-
return findFn();
467+
auto it = findFn();
468+
if (valueValidatingEnabled()) {
469+
validateValue(it);
470+
}
471+
return it;
445472
}
446473

474+
XDCHECK(!valueValidatingEnabled());
475+
447476
auto opId = valueTracker_->beginGet(key);
448477
auto it = findFn();
449478
if (checkGet(opId, it)) {

cachelib/cachebench/cache/Cache.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,9 @@ class Cache {
163163
return getSize(item.get());
164164
}
165165

166+
// checks if values stored in it matches expectedValue_.
167+
void validateValue(const ItemHandle &it) const;
168+
166169
// returns the size of the item, taking into account ItemRecords could be
167170
// enabled.
168171
uint32_t getSize(const Item* item) const noexcept;
@@ -220,9 +223,15 @@ class Cache {
220223
// @param keys list of keys that the stressor uses for the workload.
221224
void enableConsistencyCheck(const std::vector<std::string>& keys);
222225

226+
// enables validating all values on find. Each value is compared to
227+
// expected Value.
228+
void enableValueValidating(const std::string &expectedValue);
229+
223230
// returns true if the consistency checking is enabled.
224231
bool consistencyCheckEnabled() const { return valueTracker_ != nullptr; }
225232

233+
bool valueValidatingEnabled() const { return expectedValue_.has_value(); }
234+
226235
// return true if the key was previously detected to be inconsistent. This
227236
// is useful only when consistency checking is enabled by calling
228237
// enableConsistencyCheck()
@@ -345,6 +354,9 @@ class Cache {
345354
// tracker for consistency monitoring.
346355
std::unique_ptr<ValueTracker> valueTracker_;
347356

357+
// exceptected value of all items in Cache.
358+
std::optional<std::string> expectedValue_;
359+
348360
// reading of the nand bytes written for the benchmark if enabled.
349361
const uint64_t nandBytesBegin_{0};
350362

cachelib/cachebench/runner/CacheStressor.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ class CacheStressor : public Stressor {
110110
if (config_.checkConsistency) {
111111
cache_->enableConsistencyCheck(wg_->getAllKeys());
112112
}
113+
if (config_.validateValue) {
114+
cache_->enableValueValidating(hardcodedString_);
115+
}
113116
if (config_.opRatePerSec > 0) {
114117
rateLimiter_ = std::make_unique<folly::BasicTokenBucket<>>(
115118
config_.opRatePerSec, config_.opRatePerSec);

cachelib/cachebench/util/Config.cpp

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

3636
JSONSetVal(configJson, checkConsistency);
37+
JSONSetVal(configJson, validateValue);
3738

3839
JSONSetVal(configJson, numOps);
3940
JSONSetVal(configJson, numThreads);

cachelib/cachebench/util/Config.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,13 @@ struct StressorConfig : public JSONConfig {
188188
uint64_t samplingIntervalMs{1000};
189189

190190
// If enabled, stressor will verify operations' results are consistent.
191+
// Mutually exclusive with validateValue
191192
bool checkConsistency{false};
192193

194+
// If enable, stressos will verify if value read is equal to value written.
195+
// Mutually exclusive with checkConsistency
196+
bool validateValue{false};
197+
193198
uint64_t numOps{0}; // operation per thread
194199
uint64_t numThreads{0}; // number of threads that will run
195200
uint64_t numKeys{0}; // number of keys that will be used

0 commit comments

Comments
 (0)