forked from continuwuation/rocksdb
Summary: **Context/Summary:** Clear statistics reference from options_ to intentionally shorten the statistics object lifetime to be same as the db object (which is the common case in practice) and detect if RocksDB access the statistics beyond its lifetime. Pull Request resolved: https://github.com/facebook/rocksdb/pull/13899 Test Plan: - [Ongoing] Stress test rehearsal Reviewed By: pdillinger Differential Revision: D80985435 Pulled By: hx235 fbshipit-source-id: ab238231cd81f47fa451aea12a0c85fa11d9ac81
215 lines
6.3 KiB
C++
215 lines
6.3 KiB
C++
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
|
// This source code is licensed under both the GPLv2 (found in the
|
|
// COPYING file in the root directory) and Apache 2.0 License
|
|
// (found in the LICENSE.Apache file in the root directory).
|
|
|
|
#pragma once
|
|
#include <cinttypes>
|
|
#include <memory>
|
|
#include <queue>
|
|
#include <unordered_set>
|
|
|
|
#include "monitoring/histogram.h"
|
|
#include "port/port.h"
|
|
#include "rocksdb/snapshot.h"
|
|
#include "rocksdb/statistics.h"
|
|
#include "rocksdb/system_clock.h"
|
|
#include "util/gflags_compat.h"
|
|
#include "util/random.h"
|
|
|
|
DECLARE_bool(histogram);
|
|
DECLARE_bool(progress_reports);
|
|
|
|
namespace ROCKSDB_NAMESPACE {
|
|
|
|
class Stats {
|
|
private:
|
|
uint64_t start_;
|
|
uint64_t finish_;
|
|
double seconds_;
|
|
long done_;
|
|
long gets_;
|
|
long prefixes_;
|
|
long writes_;
|
|
long deletes_;
|
|
size_t single_deletes_;
|
|
long iterator_size_sums_;
|
|
long founds_;
|
|
long iterations_;
|
|
long range_deletions_;
|
|
long covered_by_range_deletions_;
|
|
long errors_;
|
|
long verified_errors_;
|
|
long num_compact_files_succeed_;
|
|
long num_compact_files_failed_;
|
|
int next_report_;
|
|
size_t bytes_;
|
|
uint64_t last_op_finish_;
|
|
HistogramImpl hist_;
|
|
|
|
public:
|
|
Stats() {}
|
|
|
|
void Start() {
|
|
next_report_ = 100;
|
|
hist_.Clear();
|
|
done_ = 0;
|
|
gets_ = 0;
|
|
prefixes_ = 0;
|
|
writes_ = 0;
|
|
deletes_ = 0;
|
|
single_deletes_ = 0;
|
|
iterator_size_sums_ = 0;
|
|
founds_ = 0;
|
|
iterations_ = 0;
|
|
range_deletions_ = 0;
|
|
covered_by_range_deletions_ = 0;
|
|
errors_ = 0;
|
|
verified_errors_ = 0;
|
|
bytes_ = 0;
|
|
seconds_ = 0;
|
|
num_compact_files_succeed_ = 0;
|
|
num_compact_files_failed_ = 0;
|
|
start_ = SystemClock::Default()->NowMicros();
|
|
last_op_finish_ = start_;
|
|
finish_ = start_;
|
|
}
|
|
|
|
void Merge(const Stats& other) {
|
|
hist_.Merge(other.hist_);
|
|
done_ += other.done_;
|
|
gets_ += other.gets_;
|
|
prefixes_ += other.prefixes_;
|
|
writes_ += other.writes_;
|
|
deletes_ += other.deletes_;
|
|
single_deletes_ += other.single_deletes_;
|
|
iterator_size_sums_ += other.iterator_size_sums_;
|
|
founds_ += other.founds_;
|
|
iterations_ += other.iterations_;
|
|
range_deletions_ += other.range_deletions_;
|
|
covered_by_range_deletions_ = other.covered_by_range_deletions_;
|
|
errors_ += other.errors_;
|
|
verified_errors_ += other.verified_errors_;
|
|
bytes_ += other.bytes_;
|
|
seconds_ += other.seconds_;
|
|
num_compact_files_succeed_ += other.num_compact_files_succeed_;
|
|
num_compact_files_failed_ += other.num_compact_files_failed_;
|
|
if (other.start_ < start_) start_ = other.start_;
|
|
if (other.finish_ > finish_) finish_ = other.finish_;
|
|
}
|
|
|
|
void Stop() {
|
|
finish_ = SystemClock::Default()->NowMicros();
|
|
seconds_ = (finish_ - start_) * 1e-6;
|
|
}
|
|
|
|
void FinishedSingleOp() {
|
|
if (FLAGS_histogram) {
|
|
auto now = SystemClock::Default()->NowMicros();
|
|
auto micros = now - last_op_finish_;
|
|
hist_.Add(micros);
|
|
if (micros > 20000) {
|
|
fprintf(stdout, "long op: %" PRIu64 " micros%30s\r", micros, "");
|
|
}
|
|
last_op_finish_ = now;
|
|
}
|
|
|
|
done_++;
|
|
if (FLAGS_progress_reports) {
|
|
if (done_ >= next_report_) {
|
|
if (next_report_ < 1000)
|
|
next_report_ += 100;
|
|
else if (next_report_ < 5000)
|
|
next_report_ += 500;
|
|
else if (next_report_ < 10000)
|
|
next_report_ += 1000;
|
|
else if (next_report_ < 50000)
|
|
next_report_ += 5000;
|
|
else if (next_report_ < 100000)
|
|
next_report_ += 10000;
|
|
else if (next_report_ < 500000)
|
|
next_report_ += 50000;
|
|
else
|
|
next_report_ += 100000;
|
|
fprintf(stdout, "... finished %ld ops%30s\r", done_, "");
|
|
}
|
|
}
|
|
}
|
|
|
|
void AddBytesForWrites(long nwrites, size_t nbytes) {
|
|
writes_ += nwrites;
|
|
bytes_ += nbytes;
|
|
}
|
|
|
|
void AddGets(long ngets, long nfounds) {
|
|
founds_ += nfounds;
|
|
gets_ += ngets;
|
|
}
|
|
|
|
void AddPrefixes(long nprefixes, long count) {
|
|
prefixes_ += nprefixes;
|
|
iterator_size_sums_ += count;
|
|
}
|
|
|
|
void AddIterations(long n) { iterations_ += n; }
|
|
|
|
void AddDeletes(long n) { deletes_ += n; }
|
|
|
|
void AddSingleDeletes(size_t n) { single_deletes_ += n; }
|
|
|
|
void AddRangeDeletions(long n) { range_deletions_ += n; }
|
|
|
|
void AddCoveredByRangeDeletions(long n) { covered_by_range_deletions_ += n; }
|
|
|
|
void AddErrors(long n) { errors_ += n; }
|
|
|
|
void AddVerifiedErrors(long n) { verified_errors_ += n; }
|
|
|
|
void AddNumCompactFilesSucceed(long n) { num_compact_files_succeed_ += n; }
|
|
|
|
void AddNumCompactFilesFailed(long n) { num_compact_files_failed_ += n; }
|
|
|
|
void Report(const char* name) {
|
|
std::string extra;
|
|
if (bytes_ < 1 || done_ < 1) {
|
|
fprintf(stderr, "No writes or ops?\n");
|
|
return;
|
|
}
|
|
|
|
double elapsed = (finish_ - start_) * 1e-6;
|
|
double bytes_mb = bytes_ / 1048576.0;
|
|
double rate = bytes_mb / elapsed;
|
|
double throughput = (double)done_ / elapsed;
|
|
|
|
fprintf(stdout, "%-12s: ", name);
|
|
fprintf(stdout, "%.3f micros/op %ld ops/sec\n", seconds_ * 1e6 / done_,
|
|
(long)throughput);
|
|
fprintf(stdout, "%-12s: Wrote %.2f MB (%.2f MB/sec) (%ld%% of %ld ops)\n",
|
|
"", bytes_mb, rate, (100 * writes_) / done_, done_);
|
|
fprintf(stdout, "%-12s: Wrote %ld times\n", "", writes_);
|
|
fprintf(stdout, "%-12s: Deleted %ld times\n", "", deletes_);
|
|
fprintf(stdout, "%-12s: Single deleted %" ROCKSDB_PRIszt " times\n", "",
|
|
single_deletes_);
|
|
fprintf(stdout, "%-12s: %ld read and %ld found the key\n", "", gets_,
|
|
founds_);
|
|
fprintf(stdout, "%-12s: Prefix scanned %ld times\n", "", prefixes_);
|
|
fprintf(stdout, "%-12s: Iterator size sum is %ld\n", "",
|
|
iterator_size_sums_);
|
|
fprintf(stdout, "%-12s: Iterated %ld times\n", "", iterations_);
|
|
fprintf(stdout, "%-12s: Deleted %ld key-ranges\n", "", range_deletions_);
|
|
fprintf(stdout, "%-12s: Range deletions covered %ld keys\n", "",
|
|
covered_by_range_deletions_);
|
|
|
|
fprintf(stdout, "%-12s: Got errors %ld times\n", "", errors_);
|
|
fprintf(stdout, "%-12s: %ld CompactFiles() succeed\n", "",
|
|
num_compact_files_succeed_);
|
|
fprintf(stdout, "%-12s: %ld CompactFiles() did not succeed\n", "",
|
|
num_compact_files_failed_);
|
|
|
|
if (FLAGS_histogram) {
|
|
fprintf(stdout, "Microseconds per op:\n%s\n", hist_.ToString().c_str());
|
|
}
|
|
fflush(stdout);
|
|
}
|
|
};
|
|
} // namespace ROCKSDB_NAMESPACE
|