Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion cachelib/cachebench/cache/Cache-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -327,13 +327,22 @@ template <typename Allocator>
void Cache<Allocator>::enableConsistencyCheck(
const std::vector<std::string>& keys) {
XDCHECK(valueTracker_ == nullptr);
XDCHECK(!valueValidatingEnabled());
valueTracker_ =
std::make_unique<ValueTracker>(ValueTracker::wrapStrings(keys));
for (const std::string& key : keys) {
invalidKeys_[key] = false;
}
}

template <typename Allocator>
void Cache<Allocator>::enableValueValidating(
const std::string &expectedValue) {
XDCHECK(!valueValidatingEnabled());
XDCHECK(!consistencyCheckEnabled());
this->expectedValue_ = expectedValue;
}

template <typename Allocator>
typename Cache<Allocator>::RemoveRes Cache<Allocator>::remove(Key key) {
if (!consistencyCheckEnabled()) {
Expand Down Expand Up @@ -426,6 +435,20 @@ typename Cache<Allocator>::ItemHandle Cache<Allocator>::insertOrReplace(
return rv;
}

template <typename Allocator>
void Cache<Allocator>::validateValue(const ItemHandle &it) const {
XDCHECK(valueValidatingEnabled());

const auto &expected = expectedValue_.value();

auto ptr = reinterpret_cast<const uint8_t*>(getMemory(it));
auto cmp = std::memcmp(ptr, expected.data(), std::min<size_t>(expected.size(),
getSize(it)));
if (cmp != 0) {
throw std::runtime_error("Value does not match!");
}
}

template <typename Allocator>
typename Cache<Allocator>::ItemHandle Cache<Allocator>::find(Key key,
AccessMode mode) {
Expand All @@ -441,9 +464,15 @@ typename Cache<Allocator>::ItemHandle Cache<Allocator>::find(Key key,
};

if (!consistencyCheckEnabled()) {
return findFn();
auto it = findFn();
if (valueValidatingEnabled()) {
validateValue(it);
}
return it;
}

XDCHECK(!valueValidatingEnabled());

auto opId = valueTracker_->beginGet(key);
auto it = findFn();
if (checkGet(opId, it)) {
Expand Down
12 changes: 12 additions & 0 deletions cachelib/cachebench/cache/Cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ class Cache {
return getSize(item.get());
}

// checks if values stored in it matches expectedValue_.
void validateValue(const ItemHandle &it) const;

// returns the size of the item, taking into account ItemRecords could be
// enabled.
uint32_t getSize(const Item* item) const noexcept;
Expand Down Expand Up @@ -220,9 +223,15 @@ class Cache {
// @param keys list of keys that the stressor uses for the workload.
void enableConsistencyCheck(const std::vector<std::string>& keys);

// enables validating all values on find. Each value is compared to
// expected Value.
void enableValueValidating(const std::string &expectedValue);

// returns true if the consistency checking is enabled.
bool consistencyCheckEnabled() const { return valueTracker_ != nullptr; }

bool valueValidatingEnabled() const { return expectedValue_.has_value(); }

// return true if the key was previously detected to be inconsistent. This
// is useful only when consistency checking is enabled by calling
// enableConsistencyCheck()
Expand Down Expand Up @@ -345,6 +354,9 @@ class Cache {
// tracker for consistency monitoring.
std::unique_ptr<ValueTracker> valueTracker_;

// exceptected value of all items in Cache.
std::optional<std::string> expectedValue_;

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

Expand Down
3 changes: 3 additions & 0 deletions cachelib/cachebench/runner/CacheStressor.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ class CacheStressor : public Stressor {
if (config_.checkConsistency) {
cache_->enableConsistencyCheck(wg_->getAllKeys());
}
if (config_.validateValue) {
cache_->enableValueValidating(hardcodedString_);
}
if (config_.opRatePerSec > 0) {
rateLimiter_ = std::make_unique<folly::BasicTokenBucket<>>(
config_.opRatePerSec, config_.opRatePerSec);
Expand Down
1 change: 1 addition & 0 deletions cachelib/cachebench/util/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ StressorConfig::StressorConfig(const folly::dynamic& configJson) {
JSONSetVal(configJson, samplingIntervalMs);

JSONSetVal(configJson, checkConsistency);
JSONSetVal(configJson, validateValue);

JSONSetVal(configJson, numOps);
JSONSetVal(configJson, numThreads);
Expand Down
5 changes: 5 additions & 0 deletions cachelib/cachebench/util/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,13 @@ struct StressorConfig : public JSONConfig {
uint64_t samplingIntervalMs{1000};

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

// If enable, stressos will verify if value read is equal to value written.
// Mutually exclusive with checkConsistency
bool validateValue{false};

uint64_t numOps{0}; // operation per thread
uint64_t numThreads{0}; // number of threads that will run
uint64_t numKeys{0}; // number of keys that will be used
Expand Down