trace_analyzer_tool.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  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. #pragma once
  6. #include <list>
  7. #include <map>
  8. #include <queue>
  9. #include <set>
  10. #include <utility>
  11. #include <vector>
  12. #include "rocksdb/env.h"
  13. #include "rocksdb/trace_reader_writer.h"
  14. #include "rocksdb/trace_record.h"
  15. #include "rocksdb/write_batch.h"
  16. #include "trace_replay/trace_replay.h"
  17. namespace ROCKSDB_NAMESPACE {
  18. // Value sizes may be used as denominators. Replacing 0 value sizes with this
  19. // positive integer avoids division error.
  20. extern const size_t kShadowValueSize /* = 10*/;
  21. enum TraceOperationType : int {
  22. kGet = 0,
  23. kPut = 1,
  24. kDelete = 2,
  25. kSingleDelete = 3,
  26. kRangeDelete = 4,
  27. kMerge = 5,
  28. kIteratorSeek = 6,
  29. kIteratorSeekForPrev = 7,
  30. kMultiGet = 8,
  31. kPutEntity = 9,
  32. kTaTypeNum = 10
  33. };
  34. struct TraceUnit {
  35. uint64_t ts;
  36. uint32_t type;
  37. uint32_t cf_id;
  38. size_t value_size;
  39. std::string key;
  40. };
  41. struct TypeCorrelation {
  42. uint64_t count;
  43. uint64_t total_ts;
  44. };
  45. struct StatsUnit {
  46. uint64_t key_id;
  47. uint64_t access_count;
  48. uint64_t latest_ts;
  49. uint64_t succ_count; // current only used to count Get if key found
  50. uint32_t cf_id;
  51. size_t value_size;
  52. std::vector<TypeCorrelation> v_correlation;
  53. };
  54. class AnalyzerOptions {
  55. public:
  56. std::vector<std::vector<int>> correlation_map;
  57. std::vector<std::pair<int, int>> correlation_list;
  58. AnalyzerOptions();
  59. ~AnalyzerOptions();
  60. void SparseCorrelationInput(const std::string& in_str);
  61. };
  62. // Note that, for the variable names in the trace_analyzer,
  63. // Starting with 'a_' means the variable is used for 'accessed_keys'.
  64. // Starting with 'w_' means it is used for 'the whole key space'.
  65. // Ending with '_f' means a file write or reader pointer.
  66. // For example, 'a_count' means 'accessed_keys_count',
  67. // 'w_key_f' means 'whole_key_space_file'.
  68. struct TraceStats {
  69. uint32_t cf_id;
  70. std::string cf_name;
  71. uint64_t a_count;
  72. uint64_t a_succ_count;
  73. uint64_t a_key_id;
  74. uint64_t a_key_size_sqsum;
  75. uint64_t a_key_size_sum;
  76. uint64_t a_key_mid;
  77. uint64_t a_value_size_sqsum;
  78. uint64_t a_value_size_sum;
  79. uint64_t a_value_mid;
  80. uint32_t a_peak_qps;
  81. double a_ave_qps;
  82. std::map<std::string, StatsUnit> a_key_stats;
  83. std::map<uint64_t, uint64_t> a_count_stats;
  84. std::map<uint64_t, uint64_t> a_key_size_stats;
  85. std::map<uint64_t, uint64_t> a_value_size_stats;
  86. std::map<uint32_t, uint32_t> a_qps_stats;
  87. std::map<uint32_t, std::map<std::string, uint32_t>> a_qps_prefix_stats;
  88. std::priority_queue<std::pair<uint64_t, std::string>,
  89. std::vector<std::pair<uint64_t, std::string>>,
  90. std::greater<std::pair<uint64_t, std::string>>>
  91. top_k_queue;
  92. std::priority_queue<std::pair<uint64_t, std::string>,
  93. std::vector<std::pair<uint64_t, std::string>>,
  94. std::greater<std::pair<uint64_t, std::string>>>
  95. top_k_prefix_access;
  96. std::priority_queue<std::pair<double, std::string>,
  97. std::vector<std::pair<double, std::string>>,
  98. std::greater<std::pair<double, std::string>>>
  99. top_k_prefix_ave;
  100. std::priority_queue<std::pair<uint32_t, uint32_t>,
  101. std::vector<std::pair<uint32_t, uint32_t>>,
  102. std::greater<std::pair<uint32_t, uint32_t>>>
  103. top_k_qps_sec;
  104. std::list<TraceUnit> time_series;
  105. std::vector<std::pair<uint64_t, uint64_t>> correlation_output;
  106. std::map<uint32_t, uint64_t> uni_key_num;
  107. std::unique_ptr<ROCKSDB_NAMESPACE::WritableFile> time_series_f;
  108. std::unique_ptr<ROCKSDB_NAMESPACE::WritableFile> a_key_f;
  109. std::unique_ptr<ROCKSDB_NAMESPACE::WritableFile> a_count_dist_f;
  110. std::unique_ptr<ROCKSDB_NAMESPACE::WritableFile> a_prefix_cut_f;
  111. std::unique_ptr<ROCKSDB_NAMESPACE::WritableFile> a_value_size_f;
  112. std::unique_ptr<ROCKSDB_NAMESPACE::WritableFile> a_key_size_f;
  113. std::unique_ptr<ROCKSDB_NAMESPACE::WritableFile> a_key_num_f;
  114. std::unique_ptr<ROCKSDB_NAMESPACE::WritableFile> a_qps_f;
  115. std::unique_ptr<ROCKSDB_NAMESPACE::WritableFile> a_top_qps_prefix_f;
  116. std::unique_ptr<ROCKSDB_NAMESPACE::WritableFile> w_key_f;
  117. std::unique_ptr<ROCKSDB_NAMESPACE::WritableFile> w_prefix_cut_f;
  118. TraceStats();
  119. ~TraceStats();
  120. TraceStats(const TraceStats&) = delete;
  121. TraceStats& operator=(const TraceStats&) = delete;
  122. TraceStats(TraceStats&&) = default;
  123. TraceStats& operator=(TraceStats&&) = default;
  124. };
  125. struct TypeUnit {
  126. std::string type_name;
  127. bool enabled;
  128. uint64_t total_keys;
  129. uint64_t total_access;
  130. uint64_t total_succ_access;
  131. uint32_t sample_count;
  132. std::map<uint32_t, TraceStats> stats;
  133. TypeUnit() = default;
  134. ~TypeUnit() = default;
  135. TypeUnit(const TypeUnit&) = delete;
  136. TypeUnit& operator=(const TypeUnit&) = delete;
  137. TypeUnit(TypeUnit&&) = default;
  138. TypeUnit& operator=(TypeUnit&&) = default;
  139. };
  140. struct CfUnit {
  141. uint32_t cf_id;
  142. uint64_t w_count; // total keys in this cf if we use the whole key space
  143. uint64_t a_count; // the total keys in this cf that are accessed
  144. std::map<uint64_t, uint64_t> w_key_size_stats; // whole key space key size
  145. // statistic this cf
  146. std::map<uint32_t, uint32_t> cf_qps;
  147. };
  148. class TraceAnalyzer : private TraceRecord::Handler,
  149. private WriteBatch::Handler {
  150. public:
  151. TraceAnalyzer(std::string& trace_path, std::string& output_path,
  152. AnalyzerOptions _analyzer_opts);
  153. ~TraceAnalyzer();
  154. Status PrepareProcessing();
  155. Status StartProcessing();
  156. Status MakeStatistics();
  157. Status ReProcessing();
  158. Status EndProcessing();
  159. Status WriteTraceUnit(TraceUnit& unit);
  160. std::vector<TypeUnit>& GetTaVector() { return ta_; }
  161. private:
  162. using TraceRecord::Handler::Handle;
  163. Status Handle(const WriteQueryTraceRecord& record,
  164. std::unique_ptr<TraceRecordResult>* result) override;
  165. Status Handle(const GetQueryTraceRecord& record,
  166. std::unique_ptr<TraceRecordResult>* result) override;
  167. Status Handle(const IteratorSeekQueryTraceRecord& record,
  168. std::unique_ptr<TraceRecordResult>* result) override;
  169. Status Handle(const MultiGetQueryTraceRecord& record,
  170. std::unique_ptr<TraceRecordResult>* result) override;
  171. using WriteBatch::Handler::PutCF;
  172. Status PutCF(uint32_t column_family_id, const Slice& key,
  173. const Slice& value) override;
  174. using WriteBatch::Handler::PutEntityCF;
  175. Status PutEntityCF(uint32_t column_family_id, const Slice& key,
  176. const Slice& value) override;
  177. using WriteBatch::Handler::DeleteCF;
  178. Status DeleteCF(uint32_t column_family_id, const Slice& key) override;
  179. using WriteBatch::Handler::SingleDeleteCF;
  180. Status SingleDeleteCF(uint32_t column_family_id, const Slice& key) override;
  181. using WriteBatch::Handler::DeleteRangeCF;
  182. Status DeleteRangeCF(uint32_t column_family_id, const Slice& begin_key,
  183. const Slice& end_key) override;
  184. using WriteBatch::Handler::MergeCF;
  185. Status MergeCF(uint32_t column_family_id, const Slice& key,
  186. const Slice& value) override;
  187. // The following hanlders are not implemented, return Status::OK() to avoid
  188. // the running time assertion and other irrelevant falures.
  189. using WriteBatch::Handler::PutBlobIndexCF;
  190. Status PutBlobIndexCF(uint32_t /*column_family_id*/, const Slice& /*key*/,
  191. const Slice& /*value*/) override {
  192. return Status::OK();
  193. }
  194. // The default implementation of LogData does nothing.
  195. using WriteBatch::Handler::LogData;
  196. void LogData(const Slice& /*blob*/) override {}
  197. using WriteBatch::Handler::MarkBeginPrepare;
  198. Status MarkBeginPrepare(bool = false) override { return Status::OK(); }
  199. using WriteBatch::Handler::MarkEndPrepare;
  200. Status MarkEndPrepare(const Slice& /*xid*/) override { return Status::OK(); }
  201. using WriteBatch::Handler::MarkNoop;
  202. Status MarkNoop(bool /*empty_batch*/) override { return Status::OK(); }
  203. using WriteBatch::Handler::MarkRollback;
  204. Status MarkRollback(const Slice& /*xid*/) override { return Status::OK(); }
  205. using WriteBatch::Handler::MarkCommit;
  206. Status MarkCommit(const Slice& /*xid*/) override { return Status::OK(); }
  207. using WriteBatch::Handler::MarkCommitWithTimestamp;
  208. Status MarkCommitWithTimestamp(const Slice& /*xid*/,
  209. const Slice& /*commit_ts*/) override {
  210. return Status::OK();
  211. }
  212. // Process each trace operation and output the analysis result to
  213. // stdout/files.
  214. Status OutputAnalysisResult(TraceOperationType op_type, uint64_t timestamp,
  215. std::vector<uint32_t> cf_ids,
  216. std::vector<Slice> keys,
  217. std::vector<size_t> value_sizes);
  218. Status OutputAnalysisResult(TraceOperationType op_type, uint64_t timestamp,
  219. uint32_t cf_id, const Slice& key,
  220. size_t value_size);
  221. ROCKSDB_NAMESPACE::Env* env_;
  222. EnvOptions env_options_;
  223. std::unique_ptr<TraceReader> trace_reader_;
  224. size_t offset_;
  225. char buffer_[1024];
  226. // Timestamp of a WriteBatch, used in its iteration.
  227. uint64_t write_batch_ts_;
  228. std::string trace_name_;
  229. std::string output_path_;
  230. AnalyzerOptions analyzer_opts_;
  231. uint64_t total_requests_;
  232. uint64_t total_access_keys_;
  233. uint64_t total_gets_;
  234. uint64_t total_writes_;
  235. uint64_t total_seeks_;
  236. uint64_t total_seek_prevs_;
  237. uint64_t total_multigets_;
  238. uint64_t trace_create_time_;
  239. uint64_t begin_time_;
  240. uint64_t end_time_;
  241. uint64_t time_series_start_;
  242. uint32_t sample_max_;
  243. uint32_t cur_time_sec_;
  244. std::unique_ptr<ROCKSDB_NAMESPACE::WritableFile>
  245. trace_sequence_f_; // readable trace
  246. std::unique_ptr<ROCKSDB_NAMESPACE::WritableFile> qps_f_; // overall qps
  247. std::unique_ptr<ROCKSDB_NAMESPACE::WritableFile>
  248. cf_qps_f_; // The qps of each CF>
  249. std::vector<TypeUnit> ta_; // The main statistic collecting data structure
  250. std::map<uint32_t, CfUnit> cfs_; // All the cf_id appears in this trace;
  251. std::vector<uint32_t> qps_peak_;
  252. std::vector<double> qps_ave_;
  253. Status ReadTraceHeader(Trace* header);
  254. Status ReadTraceFooter(Trace* footer);
  255. Status ReadTraceRecord(Trace* trace);
  256. Status KeyStatsInsertion(const uint32_t& type, const uint32_t& cf_id,
  257. const std::string& key, const size_t value_size,
  258. const uint64_t ts);
  259. Status StatsUnitCorrelationUpdate(StatsUnit& unit, const uint32_t& type,
  260. const uint64_t& ts, const std::string& key);
  261. Status OpenStatsOutputFiles(const std::string& type, TraceStats& new_stats);
  262. Status CreateOutputFile(
  263. const std::string& type, const std::string& cf_name,
  264. const std::string& ending,
  265. std::unique_ptr<ROCKSDB_NAMESPACE::WritableFile>* f_ptr);
  266. Status CloseOutputFiles();
  267. void PrintStatistics();
  268. Status TraceUnitWriter(
  269. std::unique_ptr<ROCKSDB_NAMESPACE::WritableFile>& f_ptr, TraceUnit& unit);
  270. Status WriteTraceSequence(const uint32_t& type, const uint32_t& cf_id,
  271. const Slice& key, const size_t value_size,
  272. const uint64_t ts);
  273. Status MakeStatisticKeyStatsOrPrefix(TraceStats& stats);
  274. Status MakeStatisticCorrelation(TraceStats& stats, StatsUnit& unit);
  275. Status MakeStatisticQPS();
  276. int db_version_;
  277. };
  278. int trace_analyzer_tool(int argc, char** argv);
  279. } // namespace ROCKSDB_NAMESPACE