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/env.h"
15 #include "rocksdb/snapshot.h"
16 #include "rocksdb/statistics.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 num_compact_files_succeed_;
46   long num_compact_files_failed_;
47   int next_report_;
48   size_t bytes_;
49   uint64_t last_op_finish_;
50   HistogramImpl hist_;
51 
52  public:
Stats()53   Stats() {}
54 
Start()55   void Start() {
56     next_report_ = 100;
57     hist_.Clear();
58     done_ = 0;
59     gets_ = 0;
60     prefixes_ = 0;
61     writes_ = 0;
62     deletes_ = 0;
63     single_deletes_ = 0;
64     iterator_size_sums_ = 0;
65     founds_ = 0;
66     iterations_ = 0;
67     range_deletions_ = 0;
68     covered_by_range_deletions_ = 0;
69     errors_ = 0;
70     bytes_ = 0;
71     seconds_ = 0;
72     num_compact_files_succeed_ = 0;
73     num_compact_files_failed_ = 0;
74     start_ = Env::Default()->NowMicros();
75     last_op_finish_ = start_;
76     finish_ = start_;
77   }
78 
Merge(const Stats & other)79   void Merge(const Stats& other) {
80     hist_.Merge(other.hist_);
81     done_ += other.done_;
82     gets_ += other.gets_;
83     prefixes_ += other.prefixes_;
84     writes_ += other.writes_;
85     deletes_ += other.deletes_;
86     single_deletes_ += other.single_deletes_;
87     iterator_size_sums_ += other.iterator_size_sums_;
88     founds_ += other.founds_;
89     iterations_ += other.iterations_;
90     range_deletions_ += other.range_deletions_;
91     covered_by_range_deletions_ = other.covered_by_range_deletions_;
92     errors_ += other.errors_;
93     bytes_ += other.bytes_;
94     seconds_ += other.seconds_;
95     num_compact_files_succeed_ += other.num_compact_files_succeed_;
96     num_compact_files_failed_ += other.num_compact_files_failed_;
97     if (other.start_ < start_) start_ = other.start_;
98     if (other.finish_ > finish_) finish_ = other.finish_;
99   }
100 
Stop()101   void Stop() {
102     finish_ = Env::Default()->NowMicros();
103     seconds_ = (finish_ - start_) * 1e-6;
104   }
105 
FinishedSingleOp()106   void FinishedSingleOp() {
107     if (FLAGS_histogram) {
108       auto now = Env::Default()->NowMicros();
109       auto micros = now - last_op_finish_;
110       hist_.Add(micros);
111       if (micros > 20000) {
112         fprintf(stdout, "long op: %" PRIu64 " micros%30s\r", micros, "");
113       }
114       last_op_finish_ = now;
115     }
116 
117     done_++;
118     if (FLAGS_progress_reports) {
119       if (done_ >= next_report_) {
120         if (next_report_ < 1000)
121           next_report_ += 100;
122         else if (next_report_ < 5000)
123           next_report_ += 500;
124         else if (next_report_ < 10000)
125           next_report_ += 1000;
126         else if (next_report_ < 50000)
127           next_report_ += 5000;
128         else if (next_report_ < 100000)
129           next_report_ += 10000;
130         else if (next_report_ < 500000)
131           next_report_ += 50000;
132         else
133           next_report_ += 100000;
134         fprintf(stdout, "... finished %ld ops%30s\r", done_, "");
135       }
136     }
137   }
138 
AddBytesForWrites(long nwrites,size_t nbytes)139   void AddBytesForWrites(long nwrites, size_t nbytes) {
140     writes_ += nwrites;
141     bytes_ += nbytes;
142   }
143 
AddGets(long ngets,long nfounds)144   void AddGets(long ngets, long nfounds) {
145     founds_ += nfounds;
146     gets_ += ngets;
147   }
148 
AddPrefixes(long nprefixes,long count)149   void AddPrefixes(long nprefixes, long count) {
150     prefixes_ += nprefixes;
151     iterator_size_sums_ += count;
152   }
153 
AddIterations(long n)154   void AddIterations(long n) { iterations_ += n; }
155 
AddDeletes(long n)156   void AddDeletes(long n) { deletes_ += n; }
157 
AddSingleDeletes(size_t n)158   void AddSingleDeletes(size_t n) { single_deletes_ += n; }
159 
AddRangeDeletions(long n)160   void AddRangeDeletions(long n) { range_deletions_ += n; }
161 
AddCoveredByRangeDeletions(long n)162   void AddCoveredByRangeDeletions(long n) { covered_by_range_deletions_ += n; }
163 
AddErrors(long n)164   void AddErrors(long n) { errors_ += n; }
165 
AddNumCompactFilesSucceed(long n)166   void AddNumCompactFilesSucceed(long n) { num_compact_files_succeed_ += n; }
167 
AddNumCompactFilesFailed(long n)168   void AddNumCompactFilesFailed(long n) { num_compact_files_failed_ += n; }
169 
Report(const char * name)170   void Report(const char* name) {
171     std::string extra;
172     if (bytes_ < 1 || done_ < 1) {
173       fprintf(stderr, "No writes or ops?\n");
174       return;
175     }
176 
177     double elapsed = (finish_ - start_) * 1e-6;
178     double bytes_mb = bytes_ / 1048576.0;
179     double rate = bytes_mb / elapsed;
180     double throughput = (double)done_ / elapsed;
181 
182     fprintf(stdout, "%-12s: ", name);
183     fprintf(stdout, "%.3f micros/op %ld ops/sec\n", seconds_ * 1e6 / done_,
184             (long)throughput);
185     fprintf(stdout, "%-12s: Wrote %.2f MB (%.2f MB/sec) (%ld%% of %ld ops)\n",
186             "", bytes_mb, rate, (100 * writes_) / done_, done_);
187     fprintf(stdout, "%-12s: Wrote %ld times\n", "", writes_);
188     fprintf(stdout, "%-12s: Deleted %ld times\n", "", deletes_);
189     fprintf(stdout, "%-12s: Single deleted %" ROCKSDB_PRIszt " times\n", "",
190             single_deletes_);
191     fprintf(stdout, "%-12s: %ld read and %ld found the key\n", "", gets_,
192             founds_);
193     fprintf(stdout, "%-12s: Prefix scanned %ld times\n", "", prefixes_);
194     fprintf(stdout, "%-12s: Iterator size sum is %ld\n", "",
195             iterator_size_sums_);
196     fprintf(stdout, "%-12s: Iterated %ld times\n", "", iterations_);
197     fprintf(stdout, "%-12s: Deleted %ld key-ranges\n", "", range_deletions_);
198     fprintf(stdout, "%-12s: Range deletions covered %ld keys\n", "",
199             covered_by_range_deletions_);
200 
201     fprintf(stdout, "%-12s: Got errors %ld times\n", "", errors_);
202     fprintf(stdout, "%-12s: %ld CompactFiles() succeed\n", "",
203             num_compact_files_succeed_);
204     fprintf(stdout, "%-12s: %ld CompactFiles() did not succeed\n", "",
205             num_compact_files_failed_);
206 
207     if (FLAGS_histogram) {
208       fprintf(stdout, "Microseconds per op:\n%s\n", hist_.ToString().c_str());
209     }
210     fflush(stdout);
211   }
212 };
213 }  // namespace ROCKSDB_NAMESPACE
214