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