1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. 2 // This source code is licensed under both the GPLv2 (found in the 3 // COPYING file in the root directory) and Apache 2.0 License 4 // (found in the LICENSE.Apache file in the root directory). 5 6 #pragma once 7 #include <cinttypes> 8 #include <memory> 9 #include <queue> 10 #include <unordered_set> 11 12 #include "monitoring/histogram.h" 13 #include "port/port.h" 14 #include "rocksdb/snapshot.h" 15 #include "rocksdb/statistics.h" 16 #include "rocksdb/system_clock.h" 17 #include "util/gflags_compat.h" 18 #include "util/random.h" 19 20 DECLARE_bool(histogram); 21 DECLARE_bool(progress_reports); 22 23 namespace ROCKSDB_NAMESPACE { 24 // Database statistics 25 static std::shared_ptr<ROCKSDB_NAMESPACE::Statistics> dbstats; 26 static std::shared_ptr<ROCKSDB_NAMESPACE::Statistics> dbstats_secondaries; 27 28 class Stats { 29 private: 30 uint64_t start_; 31 uint64_t finish_; 32 double seconds_; 33 long done_; 34 long gets_; 35 long prefixes_; 36 long writes_; 37 long deletes_; 38 size_t single_deletes_; 39 long iterator_size_sums_; 40 long founds_; 41 long iterations_; 42 long range_deletions_; 43 long covered_by_range_deletions_; 44 long errors_; 45 long verified_errors_; 46 long num_compact_files_succeed_; 47 long num_compact_files_failed_; 48 int next_report_; 49 size_t bytes_; 50 uint64_t last_op_finish_; 51 HistogramImpl hist_; 52 53 public: Stats()54 Stats() {} 55 Start()56 void Start() { 57 next_report_ = 100; 58 hist_.Clear(); 59 done_ = 0; 60 gets_ = 0; 61 prefixes_ = 0; 62 writes_ = 0; 63 deletes_ = 0; 64 single_deletes_ = 0; 65 iterator_size_sums_ = 0; 66 founds_ = 0; 67 iterations_ = 0; 68 range_deletions_ = 0; 69 covered_by_range_deletions_ = 0; 70 errors_ = 0; 71 verified_errors_ = 0; 72 bytes_ = 0; 73 seconds_ = 0; 74 num_compact_files_succeed_ = 0; 75 num_compact_files_failed_ = 0; 76 start_ = SystemClock::Default()->NowMicros(); 77 last_op_finish_ = start_; 78 finish_ = start_; 79 } 80 Merge(const Stats & other)81 void Merge(const Stats& other) { 82 hist_.Merge(other.hist_); 83 done_ += other.done_; 84 gets_ += other.gets_; 85 prefixes_ += other.prefixes_; 86 writes_ += other.writes_; 87 deletes_ += other.deletes_; 88 single_deletes_ += other.single_deletes_; 89 iterator_size_sums_ += other.iterator_size_sums_; 90 founds_ += other.founds_; 91 iterations_ += other.iterations_; 92 range_deletions_ += other.range_deletions_; 93 covered_by_range_deletions_ = other.covered_by_range_deletions_; 94 errors_ += other.errors_; 95 verified_errors_ += other.verified_errors_; 96 bytes_ += other.bytes_; 97 seconds_ += other.seconds_; 98 num_compact_files_succeed_ += other.num_compact_files_succeed_; 99 num_compact_files_failed_ += other.num_compact_files_failed_; 100 if (other.start_ < start_) start_ = other.start_; 101 if (other.finish_ > finish_) finish_ = other.finish_; 102 } 103 Stop()104 void Stop() { 105 finish_ = SystemClock::Default()->NowMicros(); 106 seconds_ = (finish_ - start_) * 1e-6; 107 } 108 FinishedSingleOp()109 void FinishedSingleOp() { 110 if (FLAGS_histogram) { 111 auto now = SystemClock::Default()->NowMicros(); 112 auto micros = now - last_op_finish_; 113 hist_.Add(micros); 114 if (micros > 20000) { 115 fprintf(stdout, "long op: %" PRIu64 " micros%30s\r", micros, ""); 116 } 117 last_op_finish_ = now; 118 } 119 120 done_++; 121 if (FLAGS_progress_reports) { 122 if (done_ >= next_report_) { 123 if (next_report_ < 1000) 124 next_report_ += 100; 125 else if (next_report_ < 5000) 126 next_report_ += 500; 127 else if (next_report_ < 10000) 128 next_report_ += 1000; 129 else if (next_report_ < 50000) 130 next_report_ += 5000; 131 else if (next_report_ < 100000) 132 next_report_ += 10000; 133 else if (next_report_ < 500000) 134 next_report_ += 50000; 135 else 136 next_report_ += 100000; 137 fprintf(stdout, "... finished %ld ops%30s\r", done_, ""); 138 } 139 } 140 } 141 AddBytesForWrites(long nwrites,size_t nbytes)142 void AddBytesForWrites(long nwrites, size_t nbytes) { 143 writes_ += nwrites; 144 bytes_ += nbytes; 145 } 146 AddGets(long ngets,long nfounds)147 void AddGets(long ngets, long nfounds) { 148 founds_ += nfounds; 149 gets_ += ngets; 150 } 151 AddPrefixes(long nprefixes,long count)152 void AddPrefixes(long nprefixes, long count) { 153 prefixes_ += nprefixes; 154 iterator_size_sums_ += count; 155 } 156 AddIterations(long n)157 void AddIterations(long n) { iterations_ += n; } 158 AddDeletes(long n)159 void AddDeletes(long n) { deletes_ += n; } 160 AddSingleDeletes(size_t n)161 void AddSingleDeletes(size_t n) { single_deletes_ += n; } 162 AddRangeDeletions(long n)163 void AddRangeDeletions(long n) { range_deletions_ += n; } 164 AddCoveredByRangeDeletions(long n)165 void AddCoveredByRangeDeletions(long n) { covered_by_range_deletions_ += n; } 166 AddErrors(long n)167 void AddErrors(long n) { errors_ += n; } 168 AddVerifiedErrors(long n)169 void AddVerifiedErrors(long n) { verified_errors_ += n; } 170 AddNumCompactFilesSucceed(long n)171 void AddNumCompactFilesSucceed(long n) { num_compact_files_succeed_ += n; } 172 AddNumCompactFilesFailed(long n)173 void AddNumCompactFilesFailed(long n) { num_compact_files_failed_ += n; } 174 Report(const char * name)175 void Report(const char* name) { 176 std::string extra; 177 if (bytes_ < 1 || done_ < 1) { 178 fprintf(stderr, "No writes or ops?\n"); 179 return; 180 } 181 182 double elapsed = (finish_ - start_) * 1e-6; 183 double bytes_mb = bytes_ / 1048576.0; 184 double rate = bytes_mb / elapsed; 185 double throughput = (double)done_ / elapsed; 186 187 fprintf(stdout, "%-12s: ", name); 188 fprintf(stdout, "%.3f micros/op %ld ops/sec\n", seconds_ * 1e6 / done_, 189 (long)throughput); 190 fprintf(stdout, "%-12s: Wrote %.2f MB (%.2f MB/sec) (%ld%% of %ld ops)\n", 191 "", bytes_mb, rate, (100 * writes_) / done_, done_); 192 fprintf(stdout, "%-12s: Wrote %ld times\n", "", writes_); 193 fprintf(stdout, "%-12s: Deleted %ld times\n", "", deletes_); 194 fprintf(stdout, "%-12s: Single deleted %" ROCKSDB_PRIszt " times\n", "", 195 single_deletes_); 196 fprintf(stdout, "%-12s: %ld read and %ld found the key\n", "", gets_, 197 founds_); 198 fprintf(stdout, "%-12s: Prefix scanned %ld times\n", "", prefixes_); 199 fprintf(stdout, "%-12s: Iterator size sum is %ld\n", "", 200 iterator_size_sums_); 201 fprintf(stdout, "%-12s: Iterated %ld times\n", "", iterations_); 202 fprintf(stdout, "%-12s: Deleted %ld key-ranges\n", "", range_deletions_); 203 fprintf(stdout, "%-12s: Range deletions covered %ld keys\n", "", 204 covered_by_range_deletions_); 205 206 fprintf(stdout, "%-12s: Got errors %ld times\n", "", errors_); 207 fprintf(stdout, "%-12s: %ld CompactFiles() succeed\n", "", 208 num_compact_files_succeed_); 209 fprintf(stdout, "%-12s: %ld CompactFiles() did not succeed\n", "", 210 num_compact_files_failed_); 211 212 if (FLAGS_histogram) { 213 fprintf(stdout, "Microseconds per op:\n%s\n", hist_.ToString().c_str()); 214 } 215 fflush(stdout); 216 } 217 }; 218 } // namespace ROCKSDB_NAMESPACE 219