trace_analyzer_test.cc 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727
  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. // Copyright (c) 2012 The LevelDB Authors. All rights reserved.
  7. // Use of this source code is governed by a BSD-style license that can be
  8. // found in the LICENSE file. See the AUTHORS file for names of contributors.
  9. #ifndef ROCKSDB_LITE
  10. #ifndef GFLAGS
  11. #include <cstdio>
  12. int main() {
  13. fprintf(stderr, "Please install gflags to run trace_analyzer test\n");
  14. return 1;
  15. }
  16. #else
  17. #include <chrono>
  18. #include <cstdio>
  19. #include <cstdlib>
  20. #include <sstream>
  21. #include <thread>
  22. #include "db/db_test_util.h"
  23. #include "file/read_write_util.h"
  24. #include "rocksdb/db.h"
  25. #include "rocksdb/env.h"
  26. #include "rocksdb/status.h"
  27. #include "rocksdb/trace_reader_writer.h"
  28. #include "test_util/testharness.h"
  29. #include "test_util/testutil.h"
  30. #include "tools/trace_analyzer_tool.h"
  31. #include "trace_replay/trace_replay.h"
  32. namespace ROCKSDB_NAMESPACE {
  33. namespace {
  34. static const int kMaxArgCount = 100;
  35. static const size_t kArgBufferSize = 100000;
  36. } // namespace
  37. // The helper functions for the test
  38. class TraceAnalyzerTest : public testing::Test {
  39. public:
  40. TraceAnalyzerTest() : rnd_(0xFB) {
  41. // test_path_ = test::TmpDir() + "trace_analyzer_test";
  42. test_path_ = test::PerThreadDBPath("trace_analyzer_test");
  43. env_ = ROCKSDB_NAMESPACE::Env::Default();
  44. env_->CreateDir(test_path_);
  45. dbname_ = test_path_ + "/db";
  46. }
  47. ~TraceAnalyzerTest() override {}
  48. void GenerateTrace(std::string trace_path) {
  49. Options options;
  50. options.create_if_missing = true;
  51. options.merge_operator = MergeOperators::CreatePutOperator();
  52. ReadOptions ro;
  53. WriteOptions wo;
  54. TraceOptions trace_opt;
  55. DB* db_ = nullptr;
  56. std::string value;
  57. std::unique_ptr<TraceWriter> trace_writer;
  58. Iterator* single_iter = nullptr;
  59. ASSERT_OK(
  60. NewFileTraceWriter(env_, env_options_, trace_path, &trace_writer));
  61. ASSERT_OK(DB::Open(options, dbname_, &db_));
  62. ASSERT_OK(db_->StartTrace(trace_opt, std::move(trace_writer)));
  63. WriteBatch batch;
  64. ASSERT_OK(batch.Put("a", "aaaaaaaaa"));
  65. ASSERT_OK(batch.Merge("b", "aaaaaaaaaaaaaaaaaaaa"));
  66. ASSERT_OK(batch.Delete("c"));
  67. ASSERT_OK(batch.SingleDelete("d"));
  68. ASSERT_OK(batch.DeleteRange("e", "f"));
  69. ASSERT_OK(db_->Write(wo, &batch));
  70. ASSERT_OK(db_->Get(ro, "a", &value));
  71. single_iter = db_->NewIterator(ro);
  72. single_iter->Seek("a");
  73. single_iter->SeekForPrev("b");
  74. delete single_iter;
  75. std::this_thread::sleep_for (std::chrono::seconds(1));
  76. db_->Get(ro, "g", &value);
  77. ASSERT_OK(db_->EndTrace());
  78. ASSERT_OK(env_->FileExists(trace_path));
  79. std::unique_ptr<WritableFile> whole_f;
  80. std::string whole_path = test_path_ + "/0.txt";
  81. ASSERT_OK(env_->NewWritableFile(whole_path, &whole_f, env_options_));
  82. std::string whole_str = "0x61\n0x62\n0x63\n0x64\n0x65\n0x66\n";
  83. ASSERT_OK(whole_f->Append(whole_str));
  84. delete db_;
  85. ASSERT_OK(DestroyDB(dbname_, options));
  86. }
  87. void RunTraceAnalyzer(const std::vector<std::string>& args) {
  88. char arg_buffer[kArgBufferSize];
  89. char* argv[kMaxArgCount];
  90. int argc = 0;
  91. int cursor = 0;
  92. for (const auto& arg : args) {
  93. ASSERT_LE(cursor + arg.size() + 1, kArgBufferSize);
  94. ASSERT_LE(argc + 1, kMaxArgCount);
  95. snprintf(arg_buffer + cursor, arg.size() + 1, "%s", arg.c_str());
  96. argv[argc++] = arg_buffer + cursor;
  97. cursor += static_cast<int>(arg.size()) + 1;
  98. }
  99. ASSERT_EQ(0, ROCKSDB_NAMESPACE::trace_analyzer_tool(argc, argv));
  100. }
  101. void CheckFileContent(const std::vector<std::string>& cnt,
  102. std::string file_path, bool full_content) {
  103. ASSERT_OK(env_->FileExists(file_path));
  104. std::unique_ptr<SequentialFile> f_ptr;
  105. ASSERT_OK(env_->NewSequentialFile(file_path, &f_ptr, env_options_));
  106. std::string get_line;
  107. std::istringstream iss;
  108. bool has_data = true;
  109. std::vector<std::string> result;
  110. uint32_t count;
  111. Status s;
  112. std::unique_ptr<FSSequentialFile> file =
  113. NewLegacySequentialFileWrapper(f_ptr);
  114. SequentialFileReader sf_reader(std::move(file), file_path,
  115. 4096 /* filereadahead_size */);
  116. for (count = 0; ReadOneLine(&iss, &sf_reader, &get_line, &has_data, &s);
  117. ++count) {
  118. ASSERT_OK(s);
  119. result.push_back(get_line);
  120. }
  121. ASSERT_EQ(cnt.size(), result.size());
  122. for (int i = 0; i < static_cast<int>(result.size()); i++) {
  123. if (full_content) {
  124. ASSERT_EQ(result[i], cnt[i]);
  125. } else {
  126. ASSERT_EQ(result[i][0], cnt[i][0]);
  127. }
  128. }
  129. return;
  130. }
  131. void AnalyzeTrace(std::vector<std::string>& paras_diff,
  132. std::string output_path, std::string trace_path) {
  133. std::vector<std::string> paras = {"./trace_analyzer",
  134. "-convert_to_human_readable_trace",
  135. "-output_key_stats",
  136. "-output_access_count_stats",
  137. "-output_prefix=test",
  138. "-output_prefix_cut=1",
  139. "-output_time_series",
  140. "-output_value_distribution",
  141. "-output_qps_stats",
  142. "-no_key",
  143. "-no_print"};
  144. for (auto& para : paras_diff) {
  145. paras.push_back(para);
  146. }
  147. Status s = env_->FileExists(trace_path);
  148. if (!s.ok()) {
  149. GenerateTrace(trace_path);
  150. }
  151. env_->CreateDir(output_path);
  152. RunTraceAnalyzer(paras);
  153. }
  154. ROCKSDB_NAMESPACE::Env* env_;
  155. EnvOptions env_options_;
  156. std::string test_path_;
  157. std::string dbname_;
  158. Random rnd_;
  159. };
  160. TEST_F(TraceAnalyzerTest, Get) {
  161. std::string trace_path = test_path_ + "/trace";
  162. std::string output_path = test_path_ + "/get";
  163. std::string file_path;
  164. std::vector<std::string> paras = {"-analyze_get"};
  165. paras.push_back("-output_dir=" + output_path);
  166. paras.push_back("-trace_path=" + trace_path);
  167. paras.push_back("-key_space_dir=" + test_path_);
  168. AnalyzeTrace(paras, output_path, trace_path);
  169. // check the key_stats file
  170. std::vector<std::string> k_stats = {"0 10 0 1 1.000000", "0 10 1 1 1.000000"};
  171. file_path = output_path + "/test-get-0-accessed_key_stats.txt";
  172. CheckFileContent(k_stats, file_path, true);
  173. // Check the access count distribution
  174. std::vector<std::string> k_dist = {"access_count: 1 num: 2"};
  175. file_path = output_path + "/test-get-0-accessed_key_count_distribution.txt";
  176. CheckFileContent(k_dist, file_path, true);
  177. // Check the trace sequence
  178. std::vector<std::string> k_sequence = {"1", "5", "2", "3", "4",
  179. "0", "6", "7", "0"};
  180. file_path = output_path + "/test-human_readable_trace.txt";
  181. CheckFileContent(k_sequence, file_path, false);
  182. // Check the prefix
  183. std::vector<std::string> k_prefix = {"0 0 0 0.000000 0.000000 0x30",
  184. "1 1 1 1.000000 1.000000 0x61"};
  185. file_path = output_path + "/test-get-0-accessed_key_prefix_cut.txt";
  186. CheckFileContent(k_prefix, file_path, true);
  187. // Check the time series
  188. std::vector<std::string> k_series = {"0 1533000630 0", "0 1533000630 1"};
  189. file_path = output_path + "/test-get-0-time_series.txt";
  190. CheckFileContent(k_series, file_path, false);
  191. // Check the accessed key in whole key space
  192. std::vector<std::string> k_whole_access = {"0 1"};
  193. file_path = output_path + "/test-get-0-whole_key_stats.txt";
  194. CheckFileContent(k_whole_access, file_path, true);
  195. // Check the whole key prefix cut
  196. std::vector<std::string> k_whole_prefix = {"0 0x61", "1 0x62", "2 0x63",
  197. "3 0x64", "4 0x65", "5 0x66"};
  198. file_path = output_path + "/test-get-0-whole_key_prefix_cut.txt";
  199. CheckFileContent(k_whole_prefix, file_path, true);
  200. // Check the overall qps
  201. std::vector<std::string> all_qps = {"1 0 0 0 0 0 0 0 1"};
  202. file_path = output_path + "/test-qps_stats.txt";
  203. CheckFileContent(all_qps, file_path, true);
  204. // Check the qps of get
  205. std::vector<std::string> get_qps = {"1"};
  206. file_path = output_path + "/test-get-0-qps_stats.txt";
  207. CheckFileContent(get_qps, file_path, true);
  208. // Check the top k qps prefix cut
  209. std::vector<std::string> top_qps = {"At time: 0 with QPS: 1",
  210. "The prefix: 0x61 Access count: 1"};
  211. file_path = output_path + "/test-get-0-accessed_top_k_qps_prefix_cut.txt";
  212. CheckFileContent(top_qps, file_path, true);
  213. }
  214. // Test analyzing of Put
  215. TEST_F(TraceAnalyzerTest, Put) {
  216. std::string trace_path = test_path_ + "/trace";
  217. std::string output_path = test_path_ + "/put";
  218. std::string file_path;
  219. std::vector<std::string> paras = {"-analyze_put"};
  220. paras.push_back("-output_dir=" + output_path);
  221. paras.push_back("-trace_path=" + trace_path);
  222. paras.push_back("-key_space_dir=" + test_path_);
  223. AnalyzeTrace(paras, output_path, trace_path);
  224. // check the key_stats file
  225. std::vector<std::string> k_stats = {"0 9 0 1 1.000000"};
  226. file_path = output_path + "/test-put-0-accessed_key_stats.txt";
  227. CheckFileContent(k_stats, file_path, true);
  228. // Check the access count distribution
  229. std::vector<std::string> k_dist = {"access_count: 1 num: 1"};
  230. file_path = output_path + "/test-put-0-accessed_key_count_distribution.txt";
  231. CheckFileContent(k_dist, file_path, true);
  232. // Check the trace sequence
  233. std::vector<std::string> k_sequence = {"1", "5", "2", "3", "4",
  234. "0", "6", "7", "0"};
  235. file_path = output_path + "/test-human_readable_trace.txt";
  236. CheckFileContent(k_sequence, file_path, false);
  237. // Check the prefix
  238. std::vector<std::string> k_prefix = {"0 0 0 0.000000 0.000000 0x30"};
  239. file_path = output_path + "/test-put-0-accessed_key_prefix_cut.txt";
  240. CheckFileContent(k_prefix, file_path, true);
  241. // Check the time series
  242. std::vector<std::string> k_series = {"1 1533056278 0"};
  243. file_path = output_path + "/test-put-0-time_series.txt";
  244. CheckFileContent(k_series, file_path, false);
  245. // Check the accessed key in whole key space
  246. std::vector<std::string> k_whole_access = {"0 1"};
  247. file_path = output_path + "/test-put-0-whole_key_stats.txt";
  248. CheckFileContent(k_whole_access, file_path, true);
  249. // Check the whole key prefix cut
  250. std::vector<std::string> k_whole_prefix = {"0 0x61", "1 0x62", "2 0x63",
  251. "3 0x64", "4 0x65", "5 0x66"};
  252. file_path = output_path + "/test-put-0-whole_key_prefix_cut.txt";
  253. CheckFileContent(k_whole_prefix, file_path, true);
  254. // Check the overall qps
  255. std::vector<std::string> all_qps = {"1 1 0 0 0 0 0 0 2"};
  256. file_path = output_path + "/test-qps_stats.txt";
  257. CheckFileContent(all_qps, file_path, true);
  258. // Check the qps of Put
  259. std::vector<std::string> get_qps = {"1"};
  260. file_path = output_path + "/test-put-0-qps_stats.txt";
  261. CheckFileContent(get_qps, file_path, true);
  262. // Check the top k qps prefix cut
  263. std::vector<std::string> top_qps = {"At time: 0 with QPS: 1",
  264. "The prefix: 0x61 Access count: 1"};
  265. file_path = output_path + "/test-put-0-accessed_top_k_qps_prefix_cut.txt";
  266. CheckFileContent(top_qps, file_path, true);
  267. // Check the value size distribution
  268. std::vector<std::string> value_dist = {
  269. "Number_of_value_size_between 0 and 16 is: 1"};
  270. file_path = output_path + "/test-put-0-accessed_value_size_distribution.txt";
  271. CheckFileContent(value_dist, file_path, true);
  272. }
  273. // Test analyzing of delete
  274. TEST_F(TraceAnalyzerTest, Delete) {
  275. std::string trace_path = test_path_ + "/trace";
  276. std::string output_path = test_path_ + "/delete";
  277. std::string file_path;
  278. std::vector<std::string> paras = {"-analyze_delete"};
  279. paras.push_back("-output_dir=" + output_path);
  280. paras.push_back("-trace_path=" + trace_path);
  281. paras.push_back("-key_space_dir=" + test_path_);
  282. AnalyzeTrace(paras, output_path, trace_path);
  283. // check the key_stats file
  284. std::vector<std::string> k_stats = {"0 0 0 1 1.000000"};
  285. file_path = output_path + "/test-delete-0-accessed_key_stats.txt";
  286. CheckFileContent(k_stats, file_path, true);
  287. // Check the access count distribution
  288. std::vector<std::string> k_dist = {"access_count: 1 num: 1"};
  289. file_path =
  290. output_path + "/test-delete-0-accessed_key_count_distribution.txt";
  291. CheckFileContent(k_dist, file_path, true);
  292. // Check the trace sequence
  293. std::vector<std::string> k_sequence = {"1", "5", "2", "3", "4",
  294. "0", "6", "7", "0"};
  295. file_path = output_path + "/test-human_readable_trace.txt";
  296. CheckFileContent(k_sequence, file_path, false);
  297. // Check the prefix
  298. std::vector<std::string> k_prefix = {"0 0 0 0.000000 0.000000 0x30"};
  299. file_path = output_path + "/test-delete-0-accessed_key_prefix_cut.txt";
  300. CheckFileContent(k_prefix, file_path, true);
  301. // Check the time series
  302. std::vector<std::string> k_series = {"2 1533000630 0"};
  303. file_path = output_path + "/test-delete-0-time_series.txt";
  304. CheckFileContent(k_series, file_path, false);
  305. // Check the accessed key in whole key space
  306. std::vector<std::string> k_whole_access = {"2 1"};
  307. file_path = output_path + "/test-delete-0-whole_key_stats.txt";
  308. CheckFileContent(k_whole_access, file_path, true);
  309. // Check the whole key prefix cut
  310. std::vector<std::string> k_whole_prefix = {"0 0x61", "1 0x62", "2 0x63",
  311. "3 0x64", "4 0x65", "5 0x66"};
  312. file_path = output_path + "/test-delete-0-whole_key_prefix_cut.txt";
  313. CheckFileContent(k_whole_prefix, file_path, true);
  314. // Check the overall qps
  315. std::vector<std::string> all_qps = {"1 1 1 0 0 0 0 0 3"};
  316. file_path = output_path + "/test-qps_stats.txt";
  317. CheckFileContent(all_qps, file_path, true);
  318. // Check the qps of Delete
  319. std::vector<std::string> get_qps = {"1"};
  320. file_path = output_path + "/test-delete-0-qps_stats.txt";
  321. CheckFileContent(get_qps, file_path, true);
  322. // Check the top k qps prefix cut
  323. std::vector<std::string> top_qps = {"At time: 0 with QPS: 1",
  324. "The prefix: 0x63 Access count: 1"};
  325. file_path = output_path + "/test-delete-0-accessed_top_k_qps_prefix_cut.txt";
  326. CheckFileContent(top_qps, file_path, true);
  327. }
  328. // Test analyzing of Merge
  329. TEST_F(TraceAnalyzerTest, Merge) {
  330. std::string trace_path = test_path_ + "/trace";
  331. std::string output_path = test_path_ + "/merge";
  332. std::string file_path;
  333. std::vector<std::string> paras = {"-analyze_merge"};
  334. paras.push_back("-output_dir=" + output_path);
  335. paras.push_back("-trace_path=" + trace_path);
  336. paras.push_back("-key_space_dir=" + test_path_);
  337. AnalyzeTrace(paras, output_path, trace_path);
  338. // check the key_stats file
  339. std::vector<std::string> k_stats = {"0 20 0 1 1.000000"};
  340. file_path = output_path + "/test-merge-0-accessed_key_stats.txt";
  341. CheckFileContent(k_stats, file_path, true);
  342. // Check the access count distribution
  343. std::vector<std::string> k_dist = {"access_count: 1 num: 1"};
  344. file_path = output_path + "/test-merge-0-accessed_key_count_distribution.txt";
  345. CheckFileContent(k_dist, file_path, true);
  346. // Check the trace sequence
  347. std::vector<std::string> k_sequence = {"1", "5", "2", "3", "4",
  348. "0", "6", "7", "0"};
  349. file_path = output_path + "/test-human_readable_trace.txt";
  350. CheckFileContent(k_sequence, file_path, false);
  351. // Check the prefix
  352. std::vector<std::string> k_prefix = {"0 0 0 0.000000 0.000000 0x30"};
  353. file_path = output_path + "/test-merge-0-accessed_key_prefix_cut.txt";
  354. CheckFileContent(k_prefix, file_path, true);
  355. // Check the time series
  356. std::vector<std::string> k_series = {"5 1533000630 0"};
  357. file_path = output_path + "/test-merge-0-time_series.txt";
  358. CheckFileContent(k_series, file_path, false);
  359. // Check the accessed key in whole key space
  360. std::vector<std::string> k_whole_access = {"1 1"};
  361. file_path = output_path + "/test-merge-0-whole_key_stats.txt";
  362. CheckFileContent(k_whole_access, file_path, true);
  363. // Check the whole key prefix cut
  364. std::vector<std::string> k_whole_prefix = {"0 0x61", "1 0x62", "2 0x63",
  365. "3 0x64", "4 0x65", "5 0x66"};
  366. file_path = output_path + "/test-merge-0-whole_key_prefix_cut.txt";
  367. CheckFileContent(k_whole_prefix, file_path, true);
  368. // Check the overall qps
  369. std::vector<std::string> all_qps = {"1 1 1 0 0 1 0 0 4"};
  370. file_path = output_path + "/test-qps_stats.txt";
  371. CheckFileContent(all_qps, file_path, true);
  372. // Check the qps of Merge
  373. std::vector<std::string> get_qps = {"1"};
  374. file_path = output_path + "/test-merge-0-qps_stats.txt";
  375. CheckFileContent(get_qps, file_path, true);
  376. // Check the top k qps prefix cut
  377. std::vector<std::string> top_qps = {"At time: 0 with QPS: 1",
  378. "The prefix: 0x62 Access count: 1"};
  379. file_path = output_path + "/test-merge-0-accessed_top_k_qps_prefix_cut.txt";
  380. CheckFileContent(top_qps, file_path, true);
  381. // Check the value size distribution
  382. std::vector<std::string> value_dist = {
  383. "Number_of_value_size_between 0 and 24 is: 1"};
  384. file_path =
  385. output_path + "/test-merge-0-accessed_value_size_distribution.txt";
  386. CheckFileContent(value_dist, file_path, true);
  387. }
  388. // Test analyzing of SingleDelete
  389. TEST_F(TraceAnalyzerTest, SingleDelete) {
  390. std::string trace_path = test_path_ + "/trace";
  391. std::string output_path = test_path_ + "/single_delete";
  392. std::string file_path;
  393. std::vector<std::string> paras = {"-analyze_single_delete"};
  394. paras.push_back("-output_dir=" + output_path);
  395. paras.push_back("-trace_path=" + trace_path);
  396. paras.push_back("-key_space_dir=" + test_path_);
  397. AnalyzeTrace(paras, output_path, trace_path);
  398. // check the key_stats file
  399. std::vector<std::string> k_stats = {"0 0 0 1 1.000000"};
  400. file_path = output_path + "/test-single_delete-0-accessed_key_stats.txt";
  401. CheckFileContent(k_stats, file_path, true);
  402. // Check the access count distribution
  403. std::vector<std::string> k_dist = {"access_count: 1 num: 1"};
  404. file_path =
  405. output_path + "/test-single_delete-0-accessed_key_count_distribution.txt";
  406. CheckFileContent(k_dist, file_path, true);
  407. // Check the trace sequence
  408. std::vector<std::string> k_sequence = {"1", "5", "2", "3", "4",
  409. "0", "6", "7", "0"};
  410. file_path = output_path + "/test-human_readable_trace.txt";
  411. CheckFileContent(k_sequence, file_path, false);
  412. // Check the prefix
  413. std::vector<std::string> k_prefix = {"0 0 0 0.000000 0.000000 0x30"};
  414. file_path = output_path + "/test-single_delete-0-accessed_key_prefix_cut.txt";
  415. CheckFileContent(k_prefix, file_path, true);
  416. // Check the time series
  417. std::vector<std::string> k_series = {"3 1533000630 0"};
  418. file_path = output_path + "/test-single_delete-0-time_series.txt";
  419. CheckFileContent(k_series, file_path, false);
  420. // Check the accessed key in whole key space
  421. std::vector<std::string> k_whole_access = {"3 1"};
  422. file_path = output_path + "/test-single_delete-0-whole_key_stats.txt";
  423. CheckFileContent(k_whole_access, file_path, true);
  424. // Check the whole key prefix cut
  425. std::vector<std::string> k_whole_prefix = {"0 0x61", "1 0x62", "2 0x63",
  426. "3 0x64", "4 0x65", "5 0x66"};
  427. file_path = output_path + "/test-single_delete-0-whole_key_prefix_cut.txt";
  428. CheckFileContent(k_whole_prefix, file_path, true);
  429. // Check the overall qps
  430. std::vector<std::string> all_qps = {"1 1 1 1 0 1 0 0 5"};
  431. file_path = output_path + "/test-qps_stats.txt";
  432. CheckFileContent(all_qps, file_path, true);
  433. // Check the qps of SingleDelete
  434. std::vector<std::string> get_qps = {"1"};
  435. file_path = output_path + "/test-single_delete-0-qps_stats.txt";
  436. CheckFileContent(get_qps, file_path, true);
  437. // Check the top k qps prefix cut
  438. std::vector<std::string> top_qps = {"At time: 0 with QPS: 1",
  439. "The prefix: 0x64 Access count: 1"};
  440. file_path =
  441. output_path + "/test-single_delete-0-accessed_top_k_qps_prefix_cut.txt";
  442. CheckFileContent(top_qps, file_path, true);
  443. }
  444. // Test analyzing of delete
  445. TEST_F(TraceAnalyzerTest, DeleteRange) {
  446. std::string trace_path = test_path_ + "/trace";
  447. std::string output_path = test_path_ + "/range_delete";
  448. std::string file_path;
  449. std::vector<std::string> paras = {"-analyze_range_delete"};
  450. paras.push_back("-output_dir=" + output_path);
  451. paras.push_back("-trace_path=" + trace_path);
  452. paras.push_back("-key_space_dir=" + test_path_);
  453. AnalyzeTrace(paras, output_path, trace_path);
  454. // check the key_stats file
  455. std::vector<std::string> k_stats = {"0 0 0 1 1.000000", "0 0 1 1 1.000000"};
  456. file_path = output_path + "/test-range_delete-0-accessed_key_stats.txt";
  457. CheckFileContent(k_stats, file_path, true);
  458. // Check the access count distribution
  459. std::vector<std::string> k_dist = {"access_count: 1 num: 2"};
  460. file_path =
  461. output_path + "/test-range_delete-0-accessed_key_count_distribution.txt";
  462. CheckFileContent(k_dist, file_path, true);
  463. // Check the trace sequence
  464. std::vector<std::string> k_sequence = {"1", "5", "2", "3", "4",
  465. "0", "6", "7", "0"};
  466. file_path = output_path + "/test-human_readable_trace.txt";
  467. CheckFileContent(k_sequence, file_path, false);
  468. // Check the prefix
  469. std::vector<std::string> k_prefix = {"0 0 0 0.000000 0.000000 0x30",
  470. "1 1 1 1.000000 1.000000 0x65"};
  471. file_path = output_path + "/test-range_delete-0-accessed_key_prefix_cut.txt";
  472. CheckFileContent(k_prefix, file_path, true);
  473. // Check the time series
  474. std::vector<std::string> k_series = {"4 1533000630 0", "4 1533060100 1"};
  475. file_path = output_path + "/test-range_delete-0-time_series.txt";
  476. CheckFileContent(k_series, file_path, false);
  477. // Check the accessed key in whole key space
  478. std::vector<std::string> k_whole_access = {"4 1", "5 1"};
  479. file_path = output_path + "/test-range_delete-0-whole_key_stats.txt";
  480. CheckFileContent(k_whole_access, file_path, true);
  481. // Check the whole key prefix cut
  482. std::vector<std::string> k_whole_prefix = {"0 0x61", "1 0x62", "2 0x63",
  483. "3 0x64", "4 0x65", "5 0x66"};
  484. file_path = output_path + "/test-range_delete-0-whole_key_prefix_cut.txt";
  485. CheckFileContent(k_whole_prefix, file_path, true);
  486. // Check the overall qps
  487. std::vector<std::string> all_qps = {"1 1 1 1 2 1 0 0 7"};
  488. file_path = output_path + "/test-qps_stats.txt";
  489. CheckFileContent(all_qps, file_path, true);
  490. // Check the qps of DeleteRange
  491. std::vector<std::string> get_qps = {"2"};
  492. file_path = output_path + "/test-range_delete-0-qps_stats.txt";
  493. CheckFileContent(get_qps, file_path, true);
  494. // Check the top k qps prefix cut
  495. std::vector<std::string> top_qps = {"At time: 0 with QPS: 2",
  496. "The prefix: 0x65 Access count: 1",
  497. "The prefix: 0x66 Access count: 1"};
  498. file_path =
  499. output_path + "/test-range_delete-0-accessed_top_k_qps_prefix_cut.txt";
  500. CheckFileContent(top_qps, file_path, true);
  501. }
  502. // Test analyzing of Iterator
  503. TEST_F(TraceAnalyzerTest, Iterator) {
  504. std::string trace_path = test_path_ + "/trace";
  505. std::string output_path = test_path_ + "/iterator";
  506. std::string file_path;
  507. std::vector<std::string> paras = {"-analyze_iterator"};
  508. paras.push_back("-output_dir=" + output_path);
  509. paras.push_back("-trace_path=" + trace_path);
  510. paras.push_back("-key_space_dir=" + test_path_);
  511. AnalyzeTrace(paras, output_path, trace_path);
  512. // Check the output of Seek
  513. // check the key_stats file
  514. std::vector<std::string> k_stats = {"0 0 0 1 1.000000"};
  515. file_path = output_path + "/test-iterator_Seek-0-accessed_key_stats.txt";
  516. CheckFileContent(k_stats, file_path, true);
  517. // Check the access count distribution
  518. std::vector<std::string> k_dist = {"access_count: 1 num: 1"};
  519. file_path =
  520. output_path + "/test-iterator_Seek-0-accessed_key_count_distribution.txt";
  521. CheckFileContent(k_dist, file_path, true);
  522. // Check the trace sequence
  523. std::vector<std::string> k_sequence = {"1", "5", "2", "3", "4",
  524. "0", "6", "7", "0"};
  525. file_path = output_path + "/test-human_readable_trace.txt";
  526. CheckFileContent(k_sequence, file_path, false);
  527. // Check the prefix
  528. std::vector<std::string> k_prefix = {"0 0 0 0.000000 0.000000 0x30"};
  529. file_path = output_path + "/test-iterator_Seek-0-accessed_key_prefix_cut.txt";
  530. CheckFileContent(k_prefix, file_path, true);
  531. // Check the time series
  532. std::vector<std::string> k_series = {"6 1 0"};
  533. file_path = output_path + "/test-iterator_Seek-0-time_series.txt";
  534. CheckFileContent(k_series, file_path, false);
  535. // Check the accessed key in whole key space
  536. std::vector<std::string> k_whole_access = {"0 1"};
  537. file_path = output_path + "/test-iterator_Seek-0-whole_key_stats.txt";
  538. CheckFileContent(k_whole_access, file_path, true);
  539. // Check the whole key prefix cut
  540. std::vector<std::string> k_whole_prefix = {"0 0x61", "1 0x62", "2 0x63",
  541. "3 0x64", "4 0x65", "5 0x66"};
  542. file_path = output_path + "/test-iterator_Seek-0-whole_key_prefix_cut.txt";
  543. CheckFileContent(k_whole_prefix, file_path, true);
  544. // Check the overall qps
  545. std::vector<std::string> all_qps = {"1 1 1 1 2 1 1 1 9"};
  546. file_path = output_path + "/test-qps_stats.txt";
  547. CheckFileContent(all_qps, file_path, true);
  548. // Check the qps of Iterator_Seek
  549. std::vector<std::string> get_qps = {"1"};
  550. file_path = output_path + "/test-iterator_Seek-0-qps_stats.txt";
  551. CheckFileContent(get_qps, file_path, true);
  552. // Check the top k qps prefix cut
  553. std::vector<std::string> top_qps = {"At time: 0 with QPS: 1",
  554. "The prefix: 0x61 Access count: 1"};
  555. file_path =
  556. output_path + "/test-iterator_Seek-0-accessed_top_k_qps_prefix_cut.txt";
  557. CheckFileContent(top_qps, file_path, true);
  558. // Check the output of SeekForPrev
  559. // check the key_stats file
  560. k_stats = {"0 0 0 1 1.000000"};
  561. file_path =
  562. output_path + "/test-iterator_SeekForPrev-0-accessed_key_stats.txt";
  563. CheckFileContent(k_stats, file_path, true);
  564. // Check the access count distribution
  565. k_dist = {"access_count: 1 num: 1"};
  566. file_path =
  567. output_path +
  568. "/test-iterator_SeekForPrev-0-accessed_key_count_distribution.txt";
  569. CheckFileContent(k_dist, file_path, true);
  570. // Check the prefix
  571. k_prefix = {"0 0 0 0.000000 0.000000 0x30"};
  572. file_path =
  573. output_path + "/test-iterator_SeekForPrev-0-accessed_key_prefix_cut.txt";
  574. CheckFileContent(k_prefix, file_path, true);
  575. // Check the time series
  576. k_series = {"7 0 0"};
  577. file_path = output_path + "/test-iterator_SeekForPrev-0-time_series.txt";
  578. CheckFileContent(k_series, file_path, false);
  579. // Check the accessed key in whole key space
  580. k_whole_access = {"1 1"};
  581. file_path = output_path + "/test-iterator_SeekForPrev-0-whole_key_stats.txt";
  582. CheckFileContent(k_whole_access, file_path, true);
  583. // Check the whole key prefix cut
  584. k_whole_prefix = {"0 0x61", "1 0x62", "2 0x63", "3 0x64", "4 0x65", "5 0x66"};
  585. file_path =
  586. output_path + "/test-iterator_SeekForPrev-0-whole_key_prefix_cut.txt";
  587. CheckFileContent(k_whole_prefix, file_path, true);
  588. // Check the qps of Iterator_SeekForPrev
  589. get_qps = {"1"};
  590. file_path = output_path + "/test-iterator_SeekForPrev-0-qps_stats.txt";
  591. CheckFileContent(get_qps, file_path, true);
  592. // Check the top k qps prefix cut
  593. top_qps = {"At time: 0 with QPS: 1", "The prefix: 0x62 Access count: 1"};
  594. file_path = output_path +
  595. "/test-iterator_SeekForPrev-0-accessed_top_k_qps_prefix_cut.txt";
  596. CheckFileContent(top_qps, file_path, true);
  597. }
  598. } // namespace ROCKSDB_NAMESPACE
  599. int main(int argc, char** argv) {
  600. ::testing::InitGoogleTest(&argc, argv);
  601. return RUN_ALL_TESTS();
  602. }
  603. #endif // GFLAG
  604. #else
  605. #include <stdio.h>
  606. int main(int /*argc*/, char** /*argv*/) {
  607. fprintf(stderr, "Trace_analyzer test is not supported in ROCKSDB_LITE\n");
  608. return 0;
  609. }
  610. #endif // !ROCKSDB_LITE return RUN_ALL_TESTS();