Histogram of number of merge operands

Summary:
Add a histogram in statistics to help users understand how many merge operands they merge.
Closes https://github.com/facebook/rocksdb/pull/2373

Differential Revision: D5139983

Pulled By: siying

fbshipit-source-id: 61b9ba8ca83f358530a4833d68f0103b56a0e182
This commit is contained in:
Siying Dong 2017-05-31 07:27:40 -07:00 committed by Facebook Github Bot
parent 345878a7fb
commit 51ac91f586
6 changed files with 25 additions and 11 deletions

View File

@ -562,7 +562,7 @@ void DBIter::MergeValuesNewToOld() {
const Slice val = iter_->value(); const Slice val = iter_->value();
s = MergeHelper::TimedFullMerge( s = MergeHelper::TimedFullMerge(
merge_operator_, ikey.user_key, &val, merge_context_.GetOperands(), merge_operator_, ikey.user_key, &val, merge_context_.GetOperands(),
&saved_value_, logger_, statistics_, env_, &pinned_value_); &saved_value_, logger_, statistics_, env_, &pinned_value_, true);
if (!s.ok()) { if (!s.ok()) {
status_ = s; status_ = s;
} }
@ -587,7 +587,7 @@ void DBIter::MergeValuesNewToOld() {
s = MergeHelper::TimedFullMerge(merge_operator_, saved_key_.GetUserKey(), s = MergeHelper::TimedFullMerge(merge_operator_, saved_key_.GetUserKey(),
nullptr, merge_context_.GetOperands(), nullptr, merge_context_.GetOperands(),
&saved_value_, logger_, statistics_, env_, &saved_value_, logger_, statistics_, env_,
&pinned_value_); &pinned_value_, true);
if (!s.ok()) { if (!s.ok()) {
status_ = s; status_ = s;
} }
@ -806,13 +806,13 @@ bool DBIter::FindValueForCurrentKey() {
s = MergeHelper::TimedFullMerge( s = MergeHelper::TimedFullMerge(
merge_operator_, saved_key_.GetUserKey(), nullptr, merge_operator_, saved_key_.GetUserKey(), nullptr,
merge_context_.GetOperands(), &saved_value_, logger_, statistics_, merge_context_.GetOperands(), &saved_value_, logger_, statistics_,
env_, &pinned_value_); env_, &pinned_value_, true);
} else { } else {
assert(last_not_merge_type == kTypeValue); assert(last_not_merge_type == kTypeValue);
s = MergeHelper::TimedFullMerge( s = MergeHelper::TimedFullMerge(
merge_operator_, saved_key_.GetUserKey(), &pinned_value_, merge_operator_, saved_key_.GetUserKey(), &pinned_value_,
merge_context_.GetOperands(), &saved_value_, logger_, statistics_, merge_context_.GetOperands(), &saved_value_, logger_, statistics_,
env_, &pinned_value_); env_, &pinned_value_, true);
} }
break; break;
case kTypeValue: case kTypeValue:
@ -884,7 +884,7 @@ bool DBIter::FindValueForCurrentKeyUsingSeek() {
s = MergeHelper::TimedFullMerge(merge_operator_, saved_key_.GetUserKey(), s = MergeHelper::TimedFullMerge(merge_operator_, saved_key_.GetUserKey(),
nullptr, merge_context_.GetOperands(), nullptr, merge_context_.GetOperands(),
&saved_value_, logger_, statistics_, env_, &saved_value_, logger_, statistics_, env_,
&pinned_value_); &pinned_value_, true);
// Make iter_ valid and point to saved_key_ // Make iter_ valid and point to saved_key_
if (!iter_->Valid() || if (!iter_->Valid() ||
!user_comparator_->Equal(ikey.user_key, saved_key_.GetUserKey())) { !user_comparator_->Equal(ikey.user_key, saved_key_.GetUserKey())) {
@ -902,7 +902,7 @@ bool DBIter::FindValueForCurrentKeyUsingSeek() {
s = MergeHelper::TimedFullMerge(merge_operator_, saved_key_.GetUserKey(), s = MergeHelper::TimedFullMerge(merge_operator_, saved_key_.GetUserKey(),
&val, merge_context_.GetOperands(), &val, merge_context_.GetOperands(),
&saved_value_, logger_, statistics_, env_, &saved_value_, logger_, statistics_, env_,
&pinned_value_); &pinned_value_, true);
valid_ = true; valid_ = true;
if (!s.ok()) { if (!s.ok()) {
status_ = s; status_ = s;

View File

@ -578,7 +578,7 @@ static bool SaveValue(void* arg, const char* entry) {
*(s->status) = MergeHelper::TimedFullMerge( *(s->status) = MergeHelper::TimedFullMerge(
merge_operator, s->key->user_key(), &v, merge_operator, s->key->user_key(), &v,
merge_context->GetOperands(), s->value, s->logger, s->statistics, merge_context->GetOperands(), s->value, s->logger, s->statistics,
s->env_); s->env_, nullptr /* result_operand */, true);
} else if (s->value != nullptr) { } else if (s->value != nullptr) {
s->value->assign(v.data(), v.size()); s->value->assign(v.data(), v.size());
} }
@ -595,7 +595,7 @@ static bool SaveValue(void* arg, const char* entry) {
*(s->status) = MergeHelper::TimedFullMerge( *(s->status) = MergeHelper::TimedFullMerge(
merge_operator, s->key->user_key(), nullptr, merge_operator, s->key->user_key(), nullptr,
merge_context->GetOperands(), s->value, s->logger, s->statistics, merge_context->GetOperands(), s->value, s->logger, s->statistics,
s->env_); s->env_, nullptr /* result_operand */, true);
} else { } else {
*(s->status) = Status::NotFound(); *(s->status) = Status::NotFound();
} }

View File

@ -25,7 +25,8 @@ Status MergeHelper::TimedFullMerge(const MergeOperator* merge_operator,
const std::vector<Slice>& operands, const std::vector<Slice>& operands,
std::string* result, Logger* logger, std::string* result, Logger* logger,
Statistics* statistics, Env* env, Statistics* statistics, Env* env,
Slice* result_operand) { Slice* result_operand,
bool update_num_ops_stats) {
assert(merge_operator != nullptr); assert(merge_operator != nullptr);
if (operands.size() == 0) { if (operands.size() == 0) {
@ -34,6 +35,11 @@ Status MergeHelper::TimedFullMerge(const MergeOperator* merge_operator,
return Status::OK(); return Status::OK();
} }
if (update_num_ops_stats) {
MeasureTime(statistics, READ_NUM_MERGE_OPERANDS,
static_cast<uint64_t>(operands.size()));
}
bool success; bool success;
Slice tmp_result_operand(nullptr, 0); Slice tmp_result_operand(nullptr, 0);
const MergeOperator::MergeOperationInput merge_in(key, value, operands, const MergeOperator::MergeOperationInput merge_in(key, value, operands,

View File

@ -56,6 +56,8 @@ class MergeHelper {
// Wrapper around MergeOperator::FullMergeV2() that records perf statistics. // Wrapper around MergeOperator::FullMergeV2() that records perf statistics.
// Result of merge will be written to result if status returned is OK. // Result of merge will be written to result if status returned is OK.
// If operands is empty, the value will simply be copied to result. // If operands is empty, the value will simply be copied to result.
// Set `update_num_ops_stats` to true if it is from a user read, so that
// the latency is sensitive.
// Returns one of the following statuses: // Returns one of the following statuses:
// - OK: Entries were successfully merged. // - OK: Entries were successfully merged.
// - Corruption: Merge operator reported unsuccessful merge. // - Corruption: Merge operator reported unsuccessful merge.
@ -64,7 +66,8 @@ class MergeHelper {
const std::vector<Slice>& operands, const std::vector<Slice>& operands,
std::string* result, Logger* logger, std::string* result, Logger* logger,
Statistics* statistics, Env* env, Statistics* statistics, Env* env,
Slice* result_operand = nullptr); Slice* result_operand = nullptr,
bool update_num_ops_stats = false);
// Merge entries until we hit // Merge entries until we hit
// - a corrupted key // - a corrupted key

View File

@ -1016,7 +1016,8 @@ void Version::Get(const ReadOptions& read_options, const LookupKey& k,
std::string* str_value = value != nullptr ? value->GetSelf() : nullptr; std::string* str_value = value != nullptr ? value->GetSelf() : nullptr;
*status = MergeHelper::TimedFullMerge( *status = MergeHelper::TimedFullMerge(
merge_operator_, user_key, nullptr, merge_context->GetOperands(), merge_operator_, user_key, nullptr, merge_context->GetOperands(),
str_value, info_log_, db_statistics_, env_); str_value, info_log_, db_statistics_, env_,
nullptr /* result_operand */, true);
if (LIKELY(value != nullptr)) { if (LIKELY(value != nullptr)) {
value->PinSelf(); value->PinSelf();
} }

View File

@ -370,6 +370,9 @@ enum Histograms : uint32_t {
BYTES_DECOMPRESSED, BYTES_DECOMPRESSED,
COMPRESSION_TIMES_NANOS, COMPRESSION_TIMES_NANOS,
DECOMPRESSION_TIMES_NANOS, DECOMPRESSION_TIMES_NANOS,
// Number of merge operands passed to the merge operator in user read
// requests.
READ_NUM_MERGE_OPERANDS,
HISTOGRAM_ENUM_MAX, // TODO(ldemailly): enforce HistogramsNameMap match HISTOGRAM_ENUM_MAX, // TODO(ldemailly): enforce HistogramsNameMap match
}; };
@ -405,6 +408,7 @@ const std::vector<std::pair<Histograms, std::string>> HistogramsNameMap = {
{BYTES_DECOMPRESSED, "rocksdb.bytes.decompressed"}, {BYTES_DECOMPRESSED, "rocksdb.bytes.decompressed"},
{COMPRESSION_TIMES_NANOS, "rocksdb.compression.times.nanos"}, {COMPRESSION_TIMES_NANOS, "rocksdb.compression.times.nanos"},
{DECOMPRESSION_TIMES_NANOS, "rocksdb.decompression.times.nanos"}, {DECOMPRESSION_TIMES_NANOS, "rocksdb.decompression.times.nanos"},
{READ_NUM_MERGE_OPERANDS, "rocksdb.read.num.merge_operands"},
}; };
struct HistogramData { struct HistogramData {